2011-11-01 88 views
19

这可能听起来像一场噩梦,但我真的想得到这个工作。我大部分都使用这个例子:Calling C from Haskell,并试图让这个工作在Ubuntu上。创建与JAVAH .h文件后从Java调用Haskell与C之间在

package test; 

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

这在C:

我在Java中运行这个(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编译各种不同的方式,但我一直在得到相同的错误。任何想法我可能做错了什么?

谢谢!

+0

C代码不需要在某处启动Haskell运行时?我认为你需要把它放到代码的某个地方,无论是C端还是Java端。 –

+0

您是否考虑使用JNA(https://github.com/twall/jna#readme)而不是JNI? – Landei

+1

我已经在这里回答了这个问题:http://stackoverflow.com/questions/10370177/communication-between-java-and-haskell/10370902#10370902 –

回答

3

尽管我已经在这里回答了这个问题: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库的版本。

2

如果你的目标是实际完成某事(而不是仅仅用JNI玩弄)我建议解决这个作为一个花园各种RPC问题和利用的许多框架/协议之一吧:

Protocol Buffers from Google

Thrift from Facebook

Avro (well this is mostly a wire protocol)

从你正在尝试做的,节俭可能是你最好的选择,因为它描述了一个完整的CL客户/服务器RPC堆栈,但我很确定他们中的任何一个都可以在一个简单的套接字上工作。