Domanda

In un programma Haskell, qual è il modo migliore per usare le costanti definite nelle intestazioni C?

È stato utile?

Soluzione

Per questa attività, hsc2hs è il tuo amico.

Per un semplice esempio, otteniamo il valore di INT_MAX da limits.h .

$ cat >IntMax.hsc
module Main where

#include <limits.h>

c_INT_MAX = #const INT_MAX

main = print c_INT_MAX

Con hsc2hs, possiamo #include e usare i valori delle costanti con la direttiva #const .

Invece di costruire a mano, usa 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

Nota che anche se il nome del programma principale è IntMax.hsc , la linea Main-Is punta a IntMax.hs . Quando Cabal cerca IntMax.hs ma trova IntMax.hsc , alimenta automaticamente quest'ultimo tramite hsc2hs come parte della build.

$ 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

Nota che vorrai spezzare le linee con più costanti. Supponi che stai assemblando un bitfield per passare a FormatMessage . Ti consigliamo di scriverlo come

flags = #const FORMAT_MESSAGE_FROM_SYSTEM
        .|.
        #const FORMAT_MESSAGE_IGNORE_INSERTS

Metterli tutti su una riga comporterà errori di sintassi.

Altri suggerimenti

GHC si sta allontanando da -fvia-c e verso -fasm ove possibile.

Un effetto collaterale è che il tuo programma può essere compilato senza usare alcuna intestazione C, anche in modalità -fvia-c , al fine di garantire che i risultati della compilazione siano funzionalmente identici a GHC in Modalità -fasm .

Pertanto è necessario utilizzare hsc2hs , c2hs , o altri preprocessori eseguono prima di compilazioni di GHC.

c2hs supporta nativamente le costanti enum ... è passato un po 'di tempo, ma penso che qualcosa del genere sia giusto.

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

{#enum Foo#}

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

?? #define 'd sono più complicate. Le ho sempre copiate in linea o utilizzate C aggiuntive per trasformarle in enum o variabili const.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top