Pregunta

En un programa Haskell, ¿cuál es la mejor manera de usar constantes definidas en los encabezados C?

¿Fue útil?

Solución

Para esta tarea, hsc2hs es su amigo.

Para un ejemplo simple, obtengamos el valor de INT_MAX de limits.h .

$ cat >IntMax.hsc
module Main where

#include <limits.h>

c_INT_MAX = #const INT_MAX

main = print c_INT_MAX

Con hsc2hs, podemos #include encabezados y usar los valores de las constantes con la directiva #const .

En lugar de construir 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

Observe que aunque el nombre del programa principal es IntMax.hsc , la línea Main-Is apunta a IntMax.hs . Cuando Cabal busca IntMax.hs pero encuentra IntMax.hsc , lo alimenta automáticamente a través de hsc2hs como parte de la compilación.

$ 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

Tenga en cuenta que querrá dividir líneas con múltiples constantes. Digamos que está ensamblando un campo de bits para pasar a FormatMessage . Querrás escribirlo como

flags = #const FORMAT_MESSAGE_FROM_SYSTEM
        .|.
        #const FORMAT_MESSAGE_IGNORE_INSERTS

Ponerlos todos en una línea dará como resultado errores de sintaxis.

Otros consejos

GHC se está alejando de -fvia-c y hacia -fasm siempre que sea posible.

Un efecto secundario es que su programa puede compilarse sin usar ningún encabezado C, incluso en modo -fvia-c , para garantizar que los resultados de la compilación sean funcionalmente idénticos a GHC en modo -fasm .

Por lo tanto, es necesario utilizar hsc2hs , c2hs u otros preprocesadores que ejecuten antes GHC compila fuentes.

c2hs admite de forma nativa las constantes enum ... ha pasado un tiempo, pero creo que algo así es correcto.

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

{#enum Foo#}

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

#define 'constantes son más complicadas. Siempre los he copiado en línea, o he usado C adicional para transformarlos en enumeraciones o variables constantes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top