2012-11-24 19 views
14

Sto facendo un piccolo gioco Haskell in Windows, in cui vorrei rispondere ogni volta che l'utente preme un tasto. Perché getCharbehaves strangely su Windows, utilizzo FFI per accedere a getch in conio.h, come descritto here. Il codice di riferimento è:cabal Dipendenza FFI

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

Questo funziona bene, quando l'eseguo in ghci, o compilare con GHC. Voglio anche provare a fare un pacchetto cabala fuori di esso, in modo che si estende da this domanda, includo il seguente nel mio file cabala:

... 
executable noughts 
    Includes:   conio.h 
    Extra-libraries conio 
... 

Ma quando ho eseguito cabal configure, che mi dice:

cabal: Missing dependency on a foreign library: 
* Missing C library: conio 

Ha senso, perché nella mia directory della piattaforma haskell, sotto ...\Haskell Platform\2012.4.0.0\mingw c'è un file conio.h nella directory include, ma nessun altro file conio per fornire il codice oggetto.

Sto facendo questo nel modo giusto e, in tal caso, come posso scoprire quale libreria includere nel mio file cabal?

+2

Ci sono varie librerie che forniscono le funzioni di Conio. Hai provato 'Extra-Libraries: crtdll' o' Extra-Libraries: msvcrt'? A proposito, secondo MSDN, dovresti usare '_getch' invece di' getch', ma il file di intestazione potrebbe farlo per te. –

+1

Si noti che questo riguarda solo ghc/ghci in Windows, e il codice della soluzione non funziona in particolare in WinHugs, quindi è necessario compilarlo solo quando è specificamente Windows/ghc. – AndrewC

+1

@Tinctorius Ho appena provato 'Extra-librerie: msvcrt' e' Extra-libraries: crtdll' da solo e in combinazione. Non ha cambiato l'output di 'cabal build'. Ho trovato 'msvcrt.lib' e' crtdll.c' sotto la mia installazione di Visual Studio, e li ho copiati nella mia cartella, ma non ha cambiato nulla. – Boris

risposta

7

Prima di tutto, non esiste sempre un mapping uno-a-uno tra i file di intestazione C e le librerie. In questo caso, le funzioni dichiarate in conio.h possono essere trovate in varie librerie di runtime, come ad esempio crtdll (obsoleto) o msvcrt (preferito, immagino).

con la piattaforma Haskell su Windows, Cabal cercherà queste librerie in .\mingw\lib (sotto la directory Haskell Platform): se chiedete msvcrt, cercherà .\mingw\lib\libmsvcrt.a. Questa libreria specifica dovrebbe già essere fornita con la tua piattaforma Haskell. (Se si vuole puntare a altre directory con lib*.a file, è possibile utilizzare l'opzione di Cabal --extra-lib-dirs.)

Un piccolo esempio di questo sarebbe la seguente; questo è 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' 

E questo sarebbe 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 

Questo dovrebbe funzionare bene:

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 
! 
+0

Grazie, ottimo esempio :) – Boris

+1

Per riferimento futuro, c'è da qualche parte che posso cercare quale libreria fornisce una funzione? Come hai scoperto che '_getch' è fornito da msvcrt e crtdll e che quest'ultimo è deprecato? Googling leggero non ha rivelato nulla. – Boris

+1

MSDN è (un pessimo tentativo) il manuale di sviluppo di Windows canonico, che di solito fornisce il file di intestazione e la libreria da utilizzare per una determinata funzione (puoi cercarlo con l'operatore 'site:' di Google). L'articolo su [_getch e amici] (http://msdn.microsoft.com/en-us/library/078sfkak%28v=vs.71%29.aspx) menziona solo "tutte le versioni delle librerie di runtime C" " supportalo. Dopo aver trovato 'libcrtdll.a' e' libmsvcrt.a' nella mia directory 'lib' (CRT = C run-time), ho quindi cercato Google la differenza tra' crtdll' e 'msvcrt', e ho capito che il primo è una reliquia dell'era di Windows 95. –

Problemi correlati