当前位置: 首页>>技术教程>>正文


从Java调用Haskell,中间使用C

, , , ,

问题描述

这听起来像是一场噩梦,但我真的很想让它正常工作。我在大多数情况下使用此示例:Calling C from Haskell,并试图使它在ubuntu上正常工作。

我在Java中运行此:

package test;

public class JniTest {
    public native int fib(int x);
}

使用javah创建.h文件后,在c中执行以下操作:(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);
}

然后在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

这就是我正在尝试使用的方法:

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: relocation R_X86_64_PC32 against undefined symbol `fibonacci_hs’ can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value collect2: ld returned 1 exit status

我无论如何都不是c专家,也不知道该怎么做。我尝试使用-fPIC编译各种方式,但我不断遇到相同的错误。知道我做错了什么吗?

谢谢!

最佳办法

尽管我已经在这里回答了这个问题:Communication between Java and Haskell,但是由于该问题更多地与错误本身有关,因此我将在此处添加有关该错误的详细信息。该问题源于Haskell不能很好地支持共享库,而Java需要它们。 Buildings plugins as Haskell shared libs为我们提供了这种见解和解决方法:

In principle you can use -shared without -dynamic in the link step. That would mean to statically link the rts all the base libraries into your new shared library. This would make a very big, but standalone shared library. However that would require all the static libraries to have been built with -fPIC so that the code is suitable to include into a shared library and we don’t do that at the moment.

If we use ldd again to look at the libfoo.so that we’ve made we will notice that it is missing a dependency on the rts library. This is problem that we’ve yet to sort out, so for the moment we can just add the dependency ourselves:

$ ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so \  -lHSrts-ghc6.11 -optl-Wl,-rpath,/opt/ghc/lib/ghc-6.11/ 

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

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/10124.html,未经允许,请勿转载。