Haskell: Как я могу получить значения констант # define-d? - PullRequest
2 голосов
/ 23 июня 2009

Каков наилучший способ использования констант, определенных в заголовках C, в программе на Haskell?

Ответы [ 2 ]

6 голосов
/ 23 июня 2009

Для этой задачи 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. Когда Кабал ищет 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

Размещение их всех в одну строку приведет к синтаксическим ошибкам.

4 голосов
/ 23 июня 2009

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 константы являются более хитрыми. Я всегда просто копировал их в строку или использовал дополнительный C, чтобы затем преобразовать их в перечисления или константы.

...