Question

Dans un programme Haskell, quelle est la meilleure façon d'utiliser les constantes définies dans les en-têtes C?

Était-ce utile?

La solution

Pour cette tâche, hsc2hs est votre ami.

Pour un exemple simple, obtenons la valeur de INT_MAX à limits.h .

$ cat >IntMax.hsc
module Main where

#include <limits.h>

c_INT_MAX = #const INT_MAX

main = print c_INT_MAX

Avec hsc2hs, nous pouvons utiliser les en-têtes #include et utiliser les valeurs des constantes avec la directive #const .

Au lieu de construire à la main, utilisez 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

Notez que même si le nom du programme principal est IntMax.hsc , la ligne Main-Is pointe sur IntMax.hs . Lorsque Cabal recherche IntMax.hs mais trouve IntMax.hsc , il alimente automatiquement ce dernier via hsc2hs dans le cadre de la construction.

$ 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

Notez que vous souhaiterez rompre les lignes avec plusieurs constantes. Supposons que vous soyez en train d'assembler un bitfield à FormatMessage . Vous aurez envie de l'écrire comme

flags = #const FORMAT_MESSAGE_FROM_SYSTEM
        .|.
        #const FORMAT_MESSAGE_IGNORE_INSERTS

Les mettre tous sur une seule ligne entraînera des erreurs de syntaxe.

Autres conseils

GHC s'éloigne de -fvia-c pour aller à -fasm dans la mesure du possible.

Un effet secondaire est que votre programme peut être compilé sans utiliser aucun en-tête C, même en mode -fvia-c , afin de garantir que les résultats de la compilation sont fonctionnellement identiques à ceux de GHC dans Mode -fasm .

Il est donc nécessaire d'utiliser hsc2hs , c2hs ou d'autres préprocesseurs exécutés avant GHC compile les sources.

c2hs supporte de manière native les constantes enum ... ça fait un moment, mais je pense que quelque chose comme cela est correct.

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

{#enum Foo#}

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

#define Les constantes sont plus compliquées. Je les ai toujours simplement copiés en ligne, ou utilisé un C supplémentaire pour les transformer ensuite en enums ou en variables const.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top