Haskell: Wie bekomme ich die Werte von #Define-D-Konstanten?
Frage
Was ist in einem Haskell -Programm der beste Weg, um Konstanten zu verwenden, die in C -Headern definiert sind?
Lösung
Für diese Aufgabe, HSC2HS ist dein Freund.
Lassen Sie uns für ein einfaches Beispiel den Wert von erhalten INT_MAX
aus 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 verwenden die Werte von Konstanten mit dem #const
Richtlinie.
Verwenden Sie Cabal anstatt von Hand zu bauen:
$ 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 der Name des Hauptprogramms ist, obwohl der Name des Hauptprogramms ist IntMax.hsc
, das Main-Is
Zeilenpunkte auf IntMax.hs
. Wenn Cabal nach sucht IntMax.hs
aber findet IntMax.hsc
, Es füttert letztere automatisch 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 Linien mit mehreren Konstanten aufbrechen möchten. Sagen Sie, Sie versammeln sich ein Bitfield Formatmessage. Sie werden es schreiben wollen als
flags = #const FORMAT_MESSAGE_FROM_SYSTEM
.|.
#const FORMAT_MESSAGE_IGNORE_INSERTS
Wenn Sie sie alle in eine Zeile setzen, führt dies zu Syntaxfehlern.
Andere Tipps
GHC bewegt sich weg von -fvia-c
und in Richtung -fasm
woimmer möglich.
Ein Nebeneffekt besteht -fvia-c
Modus, um sicherzustellen, dass die Kompilierungsergebnisse funktional identisch mit GHC in sind -fasm
Modus.
Somit ist es notwendig zu verwenden hsc2hs
, c2hs
, oder andere Präprozessoren laufen Vor GHC erstellt Quellen.
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 eine Zecke schwieriger. Ich habe sie immer nur inline kopiert oder zusätzliche C verwendet, um mich in Enums- oder const -Variablen zu verwandeln.