用C之间用Java调用Haskell

Cha*_*ham 19 c java linux ubuntu haskell

这可能听起来像是一场噩梦,但我真的很想让它发挥作用.我大部分时间都在使用这个例子:从Haskell调用C并尝试在ubuntu上运行.

我在java中运行它:

package test;

public class JniTest {
    public native int fib(int x);
}
Run Code Online (Sandbox Code Playgroud)

使用javah创建.h文件之后的这个:(test_JniTest.c)

#include "test_JniTest.h"
#include "Safe_stub.h"

JNIEXPORT jint JNICALL Java_test_JniTest_fib(JNIEnv * e, jobject o, jint f)
{
  return fibonacci_hs(f);
}
Run Code Online (Sandbox Code Playgroud)

然后在haskell中引用(在存根之前):( Safe.hs)

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)

这就是我正在尝试编译它:

ghc -c -O Safe.hs

其次是:

ghc -shared -o libTest.jnilib -optc -O test_JniTest.c -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun- 1.6.0.26/include/linux

我收到此错误:

/ usr/bin/ld:test_JniTest.o:在创建共享对象时,不能使用针对未定义符号"fibonacci_hs"的重定位R_X86_64_PC32; 使用-fPIC/usr/bin/ld重新编译:最终链接失败:错误值collect2:ld返回1退出状态

我不是任何方式的专家,不知道该怎么做.我尝试用-fPIC编译各种方法,但我继续得到同样的错误.知道我可能做错了什么吗?

谢谢!

Sam*_*det 3

尽管我已经在这里回答了这个问题:Communication Between Java and Haskell,因为这个问题更多的是关于错误本身,所以我将在这里添加详细信息。这个问题源于 Haskell 不能很好地支持共享库,而 Java 则需要它们。 将插件构建为 Haskell 共享库为我们提供了这种见解和解决方法:

原则上,您可以在链接步骤中使用 -shared,而不使用 -dynamic。这意味着将 rts 所有基础库静态链接到新的共享库中。这将形成一个非常大但独立的共享库。然而,这需要使用 -fPIC 构建所有静态库,以便代码适合包含到共享库中,但我们目前不这样做。

如果我们再次使用 ldd 来查看我们制作的 libfoo.so,我们会注意到它缺少对 rts 库的依赖项。这是我们尚未解决的问题,因此目前我们可以自己添加依赖项:

$ ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so \
 -lHSrts-ghc6.11 -optl-Wl,-rpath,/opt/ghc/lib/ghc-6.11/
Run Code Online (Sandbox Code Playgroud)

这是一种解决方法,因为它要求我们在构建时知道 rts 库的版本。