В программе Haskell, как лучше всего использовать константы, определенные в заголовках C?Haskell: Как получить значения констант # define-d?
ответ
Для этой задачи hsc2hs является вашим другом.
Для простого примера давайте получим значение INT_MAX
от limits.h
.
$ cat >IntMax.hsc
module Main where
#include <limits.h>
c_INT_MAX = #const INT_MAX
main = print c_INT_MAX
С hsc2hs, мы можем #include
заголовки и использовать значения констант с #const
директивы.
Вместо здания вручную, используйте 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
Обратите внимание, что даже если имя главной программы IntMax.hsc
, на Main-Is
линия указует на IntMax.hs
. Когда Cabal ищет IntMax.hs
, но находит IntMax.hsc
, он автоматически передает последний через hsc2hs как часть сборки.
$ 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
Обратите внимание, что вы захотите разбить линии с несколькими константами. Скажите, что вы собираете бит, чтобы перейти к FormatMessage. Вы хотите написать это как
flags = #const FORMAT_MESSAGE_FROM_SYSTEM
.|.
#const FORMAT_MESSAGE_IGNORE_INSERTS
Ввод их всех в одну строку приведет к ошибкам синтаксиса.
GHC отходит от -fvia-c
и в направлении -fasm
, где это возможно.
Один из побочных эффектов заключается в том, что ваша программа может быть скомпилирована без использования каких-либо C-заголовков вообще, даже в режиме -fvia-c
, чтобы гарантировать, что результаты компиляции функционально идентичны с GHC в режиме -fasm
.
Таким образом, необходимо использовать hsc2hs
, c2hs
или другие препроцессоры запустить до того GHC компилирует источники.
c2hs
изначально поддерживает enum
константы ... это было какое-то время, но я думаю, что что-то вроде этого правильно.
#c
enum Foo = { Bar, Baz };
void something(enum Foo foo) {}
#endc
{#enum Foo#}
somethingBar = {#call pure something#} (cFromEnum Bar)
#define
«D константы клещ сложнее. Я всегда просто скопировал их inline или использовал дополнительный C для преобразования в переменные enum или const.