Pergunta

Em um programa Haskell, qual é a melhor maneira de usar constantes definidas em C cabeçalhos?

Foi útil?

Solução

Para esta tarefa, HSC2HS é seu amigo.

Para um exemplo simples, vamos obter o valor de INT_MAX a partir de limits.h.

$ cat >IntMax.hsc
module Main where

#include <limits.h>

c_INT_MAX = #const INT_MAX

main = print c_INT_MAX

Com hsc2hs, podemos #include cabeçalhos e usam os valores das constantes com o #const diretivo.

Em vez de construir à mão, use 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, embora o nome do programa principal seja IntMax.hsc, a Main-Is linha aponta para IntMax.hs. Quando Cabal procura IntMax.hs mas encontra IntMax.hsc, ele alimenta automaticamente o último através do HSC2HS como parte da construção.

$ 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

Observe que você deseja interromper as linhas com várias constantes. Diga que você está montando um campo de bits para passar FormatMessage. Você vai querer escrever como

flags = #const FORMAT_MESSAGE_FROM_SYSTEM
        .|.
        #const FORMAT_MESSAGE_IGNORE_INSERTS

Colocá -los todos em uma linha resultará em erros de sintaxe.

Outras dicas

GHC é de se afastar a partir de -fvia-c e para -fasm sempre que possível.

Um efeito colateral é que o seu programa pode ser compilado sem o uso de qualquer C cabeçalhos, mesmo em -fvia-c modo, a fim de garantir que a compilação de resultados são funcionalmente idênticos para GHC em -fasm o modo.

Assim, é necessário o uso de hsc2hs, c2hs, ou outros preprocessadores executar antes de GHC compila fontes.

c2hs suporta nativamente enum constantes...tem sido um tempo, mas eu acho que algo como isto está certo.

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

{#enum Foo#}

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

#define'd constantes são uma escala mais complicado.Eu sempre apenas copiou inline, ou usado C adicional para transformar, em seguida, em enumerações ou const variáveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top