我正在开发一个涉及编译和加载用户定义的Haskell代码的项目。为此,我希望能够将Haskell模块编译为共享库(.so文件)。
我用
编译模块ghc --make -dynamic -shared -fPIC Safe.hs -o libsafe.so
和我的测试程序
ghc --make -no-hs-main -optc-O test.c -o test
两者都干净利落地编译。但是,当我运行test
时,我得到了
/usr/lib64/ghc-8.0.2/ghc-prim-0.5.0.0/libHSghc-prim-0.5.0.0-ghc8.0.2.so: undefined symbol: stg_thawArrayzh
好像我没有在某处联系某些东西,但是不应该为我处理所有这些事情?我正在使用ghc-8.0.2。
源代码是
Safe.hs
:
{-# 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
test.c
:
#include <HsFFI.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char *argv[])
{
void* handle;
hs_init(&argc, &argv);
handle = dlopen("/home/ebehn/Desktop/libsafe.so", RTLD_NOW);
if (!handle)
{
fprintf(stderr, "%s\n", dlerror());
return 2;
}
hs_exit();
return 0;
}
正在运行ldd
:
[bash]> ldd test
linux-vdso.so.1 (0x00007ffef8ff1000)
libgmp.so.10 => /lib64/libgmp.so.10 (0x00007ff046d0e000)
libm.so.6 => /lib64/libm.so.6 (0x00007ff0469c3000)
librt.so.1 => /lib64/librt.so.1 (0x00007ff0467bb000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ff0465b7000)
libffi.so.6 => /lib64/libffi.so.6 (0x00007ff0463af000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ff046191000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff045ddb000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff046f86000)
[bash]> ldd libsafe.so
linux-vdso.so.1 (0x00007ffe44bf1000)
libHSbase-4.9.1.0-ghc8.0.2.so => /usr/lib64/ghc-8.0.2/base-4.9.1.0/libHSbase-4.9.1.0-ghc8.0.2.so (0x00007fc705d0c000)
libHSinteger-gmp-1.0.0.1-ghc8.0.2.so => /usr/lib64/ghc-8.0.2/integer-gmp-1.0.0.1/libHSinteger-gmp-1.0.0.1-ghc8.0.2.so (0x00007fc705ad6000)
libHSghc-prim-0.5.0.0-ghc8.0.2.so => /usr/lib64/ghc-8.0.2/ghc-prim-0.5.0.0/libHSghc-prim-0.5.0.0-ghc8.0.2.so (0x00007fc7056d4000)
libgmp.so.10 => /lib64/libgmp.so.10 (0x00007fc70545c000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc7050a6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc706b41000)
答案 0 :(得分:0)
您正在寻找的功能在Cabal 2中实现。在.cabal
文件中,您现在可以使用foreign-library
节,这将产生一个DSO,其中所有haskell位静态链接(到目前为止)据我所知)。然后,可以将此DSO作为常规DSO加载到非haskell代码中。
使用foreign-library
:
foreign-library myforeignlib
type: native-shared
lib-version-info: 1:2:3
if os(Windows)
options: standalone
mod-def-file: MyForeignLib.def
other-modules: MyForeignLib.SomeModule
...
build-depends: base
...
hs-source-dirs: src
c-sources: csrc/some_c_code.c
答案 1 :(得分:0)
我在这里找到了一个有用的指南:https://www.vex.net/~trebla/haskell/so.xhtml
排序答案是我需要将我的库与RTS库链接:
ghc -dynamic -shared -fPIC -o libsafe.so Safe.hs -lHSrts-ghc8.2.2