Кабал FFI зависимость

Я делаю небольшую игру на Haskell в Windows, где я хотел бы отвечать каждый раз, когда пользователь нажимает клавишу. Так как getChar ведет себя странно в Windows, я использую FFI, чтобы получить доступ к getch в 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 E сть conio.h файл под include каталог, но не другой conio файл для предоставления объектного кода.

Правильно ли я делаю это, и если да, как я могу узнать, какую библиотеку включить в мой файл кабала?

1 ответ

Решение

Во-первых, не всегда существует взаимно-однозначное соответствие между заголовочными файлами C и библиотеками. В этом случае функции объявлены в conio.h можно найти в различных библиотеках времени выполнения, таких как crtdll (устарело) или msvcrt (предпочитаю, наверное).

С помощью платформы Haskell для Windows Cabal будет искать эти библиотеки в .\mingw\lib (в каталоге вашей платформы Haskell): если вы попросите msvcrtбудет искать .\mingw\lib\libmsvcrt.a, Эта конкретная библиотека уже должна поставляться с вашей платформой Haskell. (Если вы хотите указать на другие каталоги с lib*.a файлы, вы можете использовать Cabal's --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
!
Другие вопросы по тегам