首先,我指定使用Windows 10 64bit和Haskell Platform 8.0.1。
我尝试使用以下代码在Windows中使用Haskell的FFI。
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
之后,我可以用ghc很好地编译
> ghc Examples.hs
[1 of 1] Compiling Main ( Examples.hs, Examples.o )
Linking Examples.exe ...
并且它完全运行。
> Examples.exe
'1'
(当我运行它后键入1时)
但是,GHCI会出现问题。当我将其加载到ghci时,我收到了这些消息。
> 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>
我尝试加载“ missing library”,例如-lmsvcrt
需要使用的“ ” conio.h
,但结果悲观地相同。
> 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可能会加载该库,因为当我尝试加载错误的库时,ghci会输出有关该错误的信息。
我尝试了其他几种方法,例如使用ghci Examples.hs -fobject-code
,ghci -lmsvcrt Examples.hs -fobject-code
甚至
ghci Examples.hs "-luser32" "-lgdi32" "-lwinmm" "-ladvapi32" "-lshell32"
"-lshfolder" "-lwsock32" "-luser32" "-lshell32" "-lmsvcrt" "-lmingw32"
"-lmingwex" "-luser32" "-lmingw32" "-lmingwex" "-lm" "-lwsock32" "-lgdi32" "-lwinmm"
在中找到的ghc Examples.hs -v5
。
可悲的是,没有任何东西可用于我main
,并且我找不到其他任何方式。
PS有没有人知道如何在Windows中使用hSetBuffering(它发布于8年前的ghc票号#2189中。不是固定的吗?)
这是因为getch
Windows上没有。getch
是POSIX,而POSIX在Windows上已被弃用。它仍然存在,但是功能已移至其他名称空间(以将根名称空间释放给用户程序)。如您所见,MSDN说不getch
推荐使用https://msdn.microsoft.com/en-us/library/ms235446.aspx并改为使用_getch
。
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
将工作编译和解释。
至于为什么它在使用时可以编译并无法解释getch
:
该MingW-w64
项目从未像Microsoft一样删除过时的功能
因此
$ 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
被重定向到_getch
,因此它们都有两个版本。这是MSVC ++和GCC之间不兼容的根源。
但是,Microsoft已删除它们
>dumpbin /exports C:\Windows\System32\msvcr120.dll | findstr getch
699 2BA 0006B8B4 _getch = _getch
所以会发生什么,当你对链接msvcrt
:
在编译模式下,GCC和GHC都将首先选择静态库,该库恰好是import lib libmsvcrt.dll.a
。这是由于链接器(ld)的链接顺序。
在解释模式下,GHCi始终会选择动态版本的库而不是静态版本的库。原因是在重新链接期间(在引入新作用域或重新加载时必须发生),动态库要快得多,因为我们不必在内部进行重定位和符号解析。还有一些我们仍然无法正确支持的东西,例如弱符号或常见符号,因此出于这些原因,我们只喜欢动态符号。
GHCi 8.0.1不支持导入库。因此,尽管您可以强制GHCi使用静态库(只需将全名指定为-l
,例如-llibmsvcr.a
),但它不会起作用,因为运行时加载程序不知道如何处理它。但是,当前的GIT主机支持此功能,并且很可能会在8.0.2
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句