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

skv*_*rik 6 c import haskell ffi

让我们举一个常见的例子,说明如何从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
Run Code Online (Sandbox Code Playgroud)

和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;
}
Run Code Online (Sandbox Code Playgroud)

我编译并链接它:

$ ghc -c -O Safe.hs
$ ghc test.c Safe.o Safe_stub.o -o test
Run Code Online (Sandbox Code Playgroud)

没关系.但是如果我需要在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
Run Code Online (Sandbox Code Playgroud)

那不行,现在我收到一个错误:

$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_'
Run Code Online (Sandbox Code Playgroud)

我目前在这个问题上找到的就是: GHC中的一个错误,如下 变更集(更正式的bug描述)

当我使用ghc-6.12.3时,我已经实现了这个功能.所以我不知道如何解决这个问题.

也许,制作共享库并将其与我的C模块动态链接会更容易?

ehi*_*ird 4

我不认为该错误是相关的。你尝试过使用--make吗?

$ ghc -c -O Safe.hs
$ ghc --make test.c Safe.o Safe_stub.o -o test
Run Code Online (Sandbox Code Playgroud)

这些错误是您在将纯 Haskell 代码与包依赖项链接而不使用;时遇到的错误类型1 --make默认情况下, GHC 会链接进来base,但如果您想要其他包中的任何内容,则不起作用。

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

$ ghc -c -O Safe.hs
$ ghc -package bytestring test.c Safe.o Safe_stub.o -o test
Run Code Online (Sandbox Code Playgroud)

1自 GHC 7 起,--make一直是默认值。