15

我正在 Windows 中制作一个小型 Haskell 游戏,我想在用户每次按键时做出响应。因为在 Windows 上的getChar 行为很奇怪,所以我使用 FFI 来访问getchin ,如此conio.h所述。相关代码为:

foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt

当我在 ghci 中运行它或用 ghc 编译它时,这很好用。我也想尝试用它制作一个 cabal 包,所以从这个问题扩展,我在我的 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 文件中的库?

4

1 回答 1

7

首先,C 头文件和库之间并不总是存在一对一的映射。在这种情况下,conio.h可以在各种运行时库中找到其中声明的函数,例如crtdll(deprecated) 或msvcrt(preferred, I guess)。

使用 Windows 上的 Haskell 平台,Cabal 将在(在您的 Haskell 平台目录下)查找这些库.\mingw\lib:如果您要求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
!
于 2012-11-25T11:13:29.410 回答