2009-06-22 20 views

回答

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指令使用常量的值。

代替手工打造,使用惊天动地:

$ 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 

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

4

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

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

因此有必要使用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常数是一个更复杂的技巧。我总是直接复制它们,或者使用附加的C转换成枚举或const变量。