2011-11-01 86 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堆棧,但我很確定他們中的任何一個都可以在一個簡單的套接字上工作。