Haskell共享库未正确加载

时间:2018-05-08 12:31:31

标签: haskell ghc

我正在开发一个涉及编译和加载用户定义的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)

2 个答案:

答案 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