2009-06-22 13 views

Antwort

6

Für diese Aufgabe ist hsc2hs Ihr Freund. Für ein einfaches Beispiel erhalten wir den Wert INT_MAX von limits.h.

$ cat >IntMax.hsc 
module Main where 

#include <limits.h> 

c_INT_MAX = #const INT_MAX 

main = print c_INT_MAX 

Mit hsc2hs, können wir #include Header und die Werte der Konstanten mit der #const Direktive verwenden.

Statt Gebäude von Hand verwenden Cabal:

$ cat >intmax.cabal 
Name:   intmax 
Version:  0.0 
Cabal-Version: >=1.2 
Build-Type: Simple 

Executable intmax 
    Main-Is: IntMax.hs 
    Build-Depends: base 

Beachten Sie, dass, auch wenn der Name des Hauptprogramms ist IntMax.hsc, die Main-Is Linie zeigt auf IntMax.hs. Wenn Cabal nach IntMax.hs sucht, aber IntMax.hsc findet, füttert es automatisch letzteres durch hsc2hs als Teil des Builds.

$ cabal configure 
Resolving dependencies... 
Configuring intmax-0.0... 

$ cabal build 
Prerocessing executables for intmax-0.0... 
Building intmax-0.0... 
[1 of 1] Compiling Main    (dist\build\intmax\intmax-tmp\IntMax.hs, dist\build\intmax\intmax-tmp\Main.o) 
Linking dist\build\intmax\intmax.exe ... 

$ ./dist/build/intmax/intmax 
2147483647 

Beachten Sie, dass Sie Zeilen mit mehreren Konstanten aufteilen möchten. Angenommen, Sie bauen ein Bitfeld zusammen, um es an FormatMessage zu übergeben. Sie werden es als

flags = #const FORMAT_MESSAGE_FROM_SYSTEM 
     .|. 
     #const FORMAT_MESSAGE_IGNORE_INSERTS 

schreiben wollen sie alle auf einer Linie Putting wird in Syntaxfehler zur Folge haben.

4

GHC entfernt sich von -fvia-c und in Richtung -fasm, wo immer dies möglich ist.

Ein Nebeneffekt ist, dass Ihr Programm ohne Verwendung von C-Header überhaupt kompiliert werden kann, auch im -fvia-c Modus, um sicherzustellen, dass die Kompilierungsergebnisse identisch mit GHC in -fasm Modus sind.

So ist es notwendig, hsc2hs, c2hs oder andere Präprozessoren zu verwenden laufen vor GHC Quellen kompiliert.

c2hs nativ unterstützt enum Konstanten ... es ist eine Weile her, aber ich denke, so etwas ist richtig.

#c 
enum Foo = { Bar, Baz }; 
void something(enum Foo foo) {} 
#endc 

{#enum Foo#} 

somethingBar = {#call pure something#} (cFromEnum Bar) 

#define 'd Konstanten sind ein Tick Tricker. Ich habe sie immer nur inline kopiert oder zusätzliche C verwendet, um sie dann in enums oder const-Variablen umzuwandeln.