GHC/FFI:调用从C导入Haskell库的Haskell模块

6

让我们举一个常见例子,说明如何从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_'

我目前在这个问题上找到的全部信息是: GHC中的一个错误,以及以下内容变更集(有关该错误的更正式描述)
由于我正在使用ghc-6.12.3,因此我已经实现了此功能。所以我不知道如何解决这个问题。
也许,制作一个共享库并将其与我的C模块动态链接会更容易?

1
变更集比6.12.3更新,因此您仍然需要使用6.12调用hs_add_root。它甚至没有进入7.0。 - Daniel Fischer
1个回答

4

我认为那个bug和此无关。你尝试使用--make了吗?

$ ghc -c -O Safe.hs
$ ghc --make test.c Safe.o Safe_stub.o -o test

在不使用--make的情况下,将纯Haskell代码与包依赖项链接时,会出现这些错误类型。 GHC默认链接base,但如果您需要来自其他包的任何内容,则可能无法正常工作。

如果您想要更多的“手动”方法,也可以尝试明确指定包:

$ ghc -c -O Safe.hs
$ ghc -package bytestring test.c Safe.o Safe_stub.o -o test

1从 GHC 7 开始,--make 是默认选项。


谢谢,这正是我需要的,太简单了 :) 我浪费了很多时间来尝试链接它。 - skvadrik
$ ghc -c -O Safe.hs$ ghc -package bytestring test.c Safe.o Safe_stub.o -o test - skvadrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接