我在java中运行它:
package test; public class JniTest { public native int fib(int x); }在使用javah创建.h文件之后,在c中:(test_JniTest.c )
#includetest_JniTest.h #includeSafe_stub.h JNIEXPORT jint JNICALL Java_test_JniTest_fib(JNIEnv * e,jobject o,jint f) { return fibonacci_hs(f); $ / code>然后在haskell(存根前)中引用:(Safe.hs)
模块安全其中 导入Foreign.C.Types 斐波纳契:: Int - > Int fibonacci n = fibs !! n 其中fibs = 0:1:zipWith(+)fibs(尾纤) fibonacci_hs :: CInt - > CInt fibonacci_hs = fromIntegral。斐波纳契。 fromIntegral 国外出口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:搬迁对$ b R_X86_64_PC32 $ b未定义符号`fibonacci_hs'在制作共享的对象时不能使用;使用-fPIC / usr / bin / ld重新编译:最终链接失败:错误值 collect2:ld返回1退出状态
我不是任何方式的专家,也不知道该怎么做。我尝试用-fPIC编译各种不同的方式,但我一直在得到相同的错误。任何想法,我可能做错了什么?
谢谢!
解决方案尽管我已经在这里回答了这个问题: Java与Haskell之间的通信,因为这个问题更多的是关于错误本身,所以我会在这里添加细节。这个问题源于Haskell不是很好地支持共享库,而Java需要它们。 建筑物插件与Haskell共享库为我们提供了这种见解和解决方法:
原则上,您可以在链接步骤中使用没有-dynamic的-shared。这意味着将所有基础库的静态链接到新的共享库中。这将会形成一个非常大但独立的共享库。然而,这将需要所有的静态库都使用-fPIC构建,以便代码适合包含到共享库中,而我们目前不这样做。
如果我们再次使用ldd来查看我们所做的libfoo.so,我们会注意到它缺少对rts库的依赖。这是我们尚未解决的问题,所以目前我们可以自己添加依赖项:
$ ghc --make -dynamic -fPIC -shared -o Foo.hs \ libfoo.so -lHSrts-ghc6.11 -optl-WL,-rpath为/ opt / GHC / lib中/ ghc6.11 /
这是一种解决方法,因为它要求我们知道rts的版本图书馆在建设时间。
This probably sounds like a nightmare, but I'd really like to get this working. I am using this example for the most part: Calling C from Haskell and am trying to get this working on ubuntu.
I am running this in java:
package test; public class JniTest { public native int fib(int x); }this in c after creating the .h file with javah: (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); }and then for reference in haskell (before stub): (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 -> CIntand this is what i'm trying to compile it with:
ghc -c -O Safe.hs
followed by:
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
and I am getting this error:
/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
I am not a c expert by any means and have no idea what to do about this. I tried compiling various ways with -fPIC, but I kept on getting the same error. Any idea what I might be doing wrong?
Thanks!
解决方案Although I've pretty much answered this question here: Communication between Java and Haskell, since this issue is more about the error itself, I will be adding the details for that here. The issue stems from Haskell not supporting shared libraries very well, while Java requires them. Buildings plugins as Haskell shared libs gives us this insight and workaround:
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/
This is a workaround because it requires us to know the version of the rts library at build time.
更多推荐
从C中调用Java的Haskell
发布评论