Haskell:我如何获得#define-d常量的值?

时间:2009-06-22 21:42:15

标签: haskell ffi cabal hsc2hs

在Haskell程序中,使用C头中定义的常量的最佳方法是什么?

2 个答案:

答案 0 :(得分:6)

对于此任务,hsc2hs是您的朋友。

举一个简单的例子,让我们从limits.h获取INT_MAX的值。

$ 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.hscMain-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

将它们全部放在一行会导致语法错误。

答案 1 :(得分:4)

GHC正在尽可能地从-fvia-c转向-fasm

一个副作用是,即使在-fvia-c模式下,您的程序也可以在不使用任何C头的情况下进行编译,以确保编译结果在功能上与-fasm模式下的GHC相同

因此,在 GHC编译源代码之前,必须使用hsc2hsc2hs或运行的其他预处理器。

c2hs本身支持enum常量......已经有一段时间了,但我认为这样的事情是正确的。

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

{#enum Foo#}

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

#define'常量是一个棘手的问题。我总是将它们内联复制,或者使用额外的C转换为枚举或常量变量。