Interface de fonction étrangère Haskell avec GHCI dans Windows

Tout d’abord, je spécifie que j’utilise Windows 10 64 bits et Haskell Platform 8.0.1.

J’essaie d’utiliser FFI de Haskell dans Windows en utilisant le code suivant.

import Control.Monad import Data.Char import Foreign.C getCh :: IO Char getCh = liftM (chr . fromEnum) c_getch foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt main :: IO () main = getCh >>= \x -> print x 

Après cela, je peux bien comstackr ça avec ghc

 > ghc Examples.hs [1 of 1] Compiling Main ( Examples.hs, Examples.o ) Linking Examples.exe ... 

et ça marche complètement.

 > Examples.exe '1' 

(Quand je tape 1 après l’avoir exécuté)

Cependant, le problème se produit avec GHCI. Lorsque je le charge sur ghci, j’ai ces messages.

 > ghci Examples.hs GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help [1 of 1] Compiling Main ( Examples.hs, interpreted ) Ok, modules loaded: Main. *Main> main ByteCodeLink: can't find label During interactive linking, GHCi couldn't find the following symbol: getch This may be due to you not asking GHCi to load extra object files, archives or DLLs needed by your current session. Restart GHCi, specifying the missing library using the -L/path/to/object/dir and -lmissinglibname flags, or simply by naming the relevant files on the GHCi command line. Alternatively, this link failure might indicate a bug in GHCi. If you suspect the latter, please send a bug report to: [email protected] *Main> 

J’essaie de charger “bibliothèque manquante”, tel que ” -lmsvcrt ” qui doit utiliser conio.h , mais le résultat est conio.h identique.

 > ghci -lmsvcrt Examples.hs GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help [1 of 1] Compiling Main ( Examples.hs, interpreted ) Ok, modules loaded: Main. *Main> main ByteCodeLink: can't find label During interactive linking, GHCi couldn't find the following symbol: getch This may be due to you not asking GHCi to load extra object files, archives or DLLs needed by your current session. Restart GHCi, specifying the missing library using the -L/path/to/object/dir and -lmissinglibname flags, or simply by naming the relevant files on the GHCi command line. Alternatively, this link failure might indicate a bug in GHCi. If you suspect the latter, please send a bug report to: [email protected] *Main> 

GHCI charge probablement la bibliothèque, car lorsque j’essaye de charger une mauvaise bibliothèque, ghci imprime des erreurs à ce sujet.

J’essaie plusieurs autres choses, comme l’utilisation de ghci Examples.hs -fobject-code , ghci -lmsvcrt Examples.hs -fobject-code et même

 ghci Examples.hs "-luser32" "-lgdi32" "-lwinmm" "-ladvapi32" "-lshell32" "-lshfolder" "-lwsock32" "-luser32" "-lshell32" "-lmsvcrt" "-lmingw32" "-lmingwex" "-luser32" "-lmingw32" "-lmingwex" "-lm" "-lwsock32" "-lgdi32" "-lwinmm" 

Qui a été trouvé dans ghc Examples.hs -v5 .

Malheureusement, rien ne fonctionne pour mon main , et je ne peux pas trouver d’autre solution pour cela.

PS Y a-t-il quelqu’un qui sache comment utiliser hSetBuffering sous Windows (il a été publié il y a 8 ans dans le dossier ghc n ° 2189 ? N’est-ce pas corrigé?)

Cela est dû au fait qu’il n’ya pas de getch sur Windows. getch est POSIX et POSIX est devenu obsolète sous Windows. Il est toujours là, mais les fonctions ont été déplacées vers un autre espace de noms (pour libérer l’espace de noms racine des programmes utilisateur). Comme vous pouvez le voir, MSDN dit que getch est obsolète https://msdn.microsoft.com/en-us/library/ms235446.aspx et que vous _getch utiliser _getch place.

 import Control.Monad import Data.Char import Foreign.C getCh :: IO Char getCh = liftM (chr . fromEnum) c_getch foreign import ccall unsafe "conio.h _getch" c_getch :: IO CInt main :: IO () main = getCh >>= \x -> print x 

Travaillera à la fois compilé et interprété.

En ce qui concerne le pourquoi cela fonctionne compilé et non interprété en utilisant getch :

Le projet MingW-w64 n’a jamais supprimé les fonctions obsolètes comme Microsoft l’a fait.

En tant que tel

 $ objdump -t /home/Tamar/ghc2/inplace/mingw/x86_64-w64-mingw32/lib/libmsvcr120.a | grep getch [ 7](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 getch [ 8](sec 5)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 __imp_getch [ 7](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _getch [ 8](sec 5)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 __imp__getch 

getch est redirigé vers _getch et ils ont donc les deux versions. Ceci est une source d’incompatibilité entre MSVC ++ et GCC.

Microsoft les a toutefois supprimés

 >dumpbin /exports C:\Windows\System32\msvcr120.dll | findstr getch 699 2BA 0006B8B4 _getch = _getch 

Alors, que se passe-t-il lorsque vous msvcrt lien avec msvcrt :

  1. En mode compilé, GCC et GHC libmsvcrt.dll.a abord la bibliothèque statique, qui se trouve être une lib libmsvcrt.dll.a importation. Cela est dû à l’ordre des liens de l’éditeur de liens (ld).

  2. En mode interprété, GHCi préférera toujours la version dynamic de la bibliothèque à la version statique. La raison en est lors de la re-liaison (ce qui doit se produire lorsque vous introduisez une nouvelle étendue ou un nouveau rechargement). Les bibliothèques dynamics sont beaucoup plus rapides car nous n’avons pas à effectuer de relocalisation interne et de résolution de symboles. Il y a aussi des choses que nous ne supportons toujours pas correctement comme des symboles faibles ou des symboles communs, donc pour ces raisons, nous préférons simplement la dynamic.

  3. GHCi 8.0.1 ne prend pas en charge les bibliothèques d’importation. Donc, alors que vous pouvez forcer GHCi à utiliser la bibliothèque statique (donnez simplement le nom complet à -l , par exemple -llibmsvcr.a ) Cela ne fonctionnera pas car le chargeur d’exécution ne sait pas quoi en faire. Ceci est cependant pris en charge dans le maître GIT actuel et sera probablement dans la version 8.0.2