【发布时间】:2012-01-11 15:53:20
【问题描述】:
让我们举一个常见的例子,如何从 C 函数中调用 haskell 函数:
Haskell 模块:
{-# LANGUAGE ForeignFunctionInterface #-}
module Safe where
import Foreign.C.Types
fibonacci :: Int -> Int
fibonacci n = fibs !! n
where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral
foreign export ccall fibonacci_hs :: CInt -> CInt
和C模块:
#include <HsFFI.h>
#ifdef __GLASGOW_HASKELL__
#include "Safe_stub.h"
extern void __stginit_Safe(void);
#endif
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
hs_init(&argc, &argv);
#ifdef __GLASGOW_HASKELL__
hs_add_root(__stginit_Safe);
#endif
i = fibonacci_hs(42);
printf("Fibonacci: %d\n", i);
hs_exit();
return 0;
}
我编译并链接它:
$ ghc -c -O Safe.hs
$ ghc test.c Safe.o Safe_stub.o -o test
没关系。但是如果我需要在 haskell 模块中导入一些库怎么办?例如,如果我需要使用字节串,我应该添加“import Data.Bytestring.Char8”(此模块仅作为示例,代码中未使用):
{-# LANGUAGE ForeignFunctionInterface #-}
module Safe where
import Foreign.C.Types
import Data.Bytestring.Char8
fibonacci :: Int -> Int
fibonacci n = fibs !! n
where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral
foreign export ccall fibonacci_hs :: CInt -> CInt
那不行,现在我得到一个错误:
$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_'
我目前发现的所有问题都是这样的: a bug in GHC 如下 changeset (more formal description of the bug)
当我使用 ghc-6.12.3 时,我已经实现了这个功能。所以我不知道如何解决这个问题。
也许,创建一个共享库并将其与我的 C 模块动态链接会更容易?
【问题讨论】:
-
变更集比 6.12.3 更新,因此您仍然需要使用 6.12 调用
hs_add_root。它甚至没有进入 7.0。