我正在Windows中制作一个小型Haskell游戏,我希望每次用户按下一个键时都会响应。由于Windows上的getChar
behaves strangely,我使用FFI访问getch
中的conio.h
,如here所述。相关代码是:
foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt
当我在ghci中运行它或使用ghc编译时,这很好用。我还想尝试制作一个cabal包,所以从this问题延伸,我在我的cabal文件中包含以下内容:
...
executable noughts
Includes: conio.h
Extra-libraries conio
...
但是当我运行cabal configure
时,它会告诉我:
cabal: Missing dependency on a foreign library:
* Missing C library: conio
这是有道理的,因为在我的haskell平台目录中,在...\Haskell Platform\2012.4.0.0\mingw
下conio.h
目录下有一个include
文件,但没有其他conio
文件提供目标代码。
我是以正确的方式做到这一点,如果是这样,我怎样才能找出要包含在我的cabal文件中的库?
答案 0 :(得分:7)
首先,C头文件和库之间并不总是一对一的映射。在这种情况下,conio.h
中声明的函数可以在各种运行时库中找到,例如crtdll
(不建议使用)或msvcrt
(首选,我猜)。
使用Windows上的Haskell平台,Cabal将在.\mingw\lib
(在您的Haskell平台目录下)中查找这些库:如果您要求msvcrt
,它将查找.\mingw\lib\libmsvcrt.a
。这个特定的库应该已经与您的Haskell平台一起提供。 (如果要指向包含lib*.a
个文件的其他目录,可以使用Cabal的--extra-lib-dirs
选项。)
这方面的一个很好的例子如下;这是Main.hs
:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
foreign import ccall unsafe "conio.h _putch" c_putch :: CInt -> IO ()
main :: IO ()
main = do
c_putch . toEnum . fromEnum $ '!'
c_putch . toEnum . fromEnum $ '\n'
这将是something-awesome.cabal
:
name: something-awesome
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.8
executable yay
main-is: Main.hs
build-depends: base ==4.5.*
includes: conio.h
extra-libraries: msvcrt
这应该可以正常工作:
c:\tmp\something-awesome> dir /B
Main.hs
something-awesome.cabal
c:\tmp\something-awesome> cabal configure
Resolving dependencies...
Configuring something-awesome-0.1.0.0...
c:\tmp\something-awesome> cabal build
Building something-awesome-0.1.0.0...
Preprocessing executable 'yay' for something-awesome-0.1.0.0...
[1 of 1] Compiling Main ( Main.hs, dist\build\yay\yay-tmp\Main.o )
Linking dist\build\yay\yay.exe ...
c:\tmp\something-awesome> dist\build\yay\yay.exe
!