JavaCPP,在 JAR 中归档本机库时出现 UnsatisfiedLinkError [英] JavaCPP, UnsatisfiedLinkError when native library is archived in JAR
问题描述
我正在尝试从 Java 调用 Haskell 代码,使用 JavaCPP 来帮助创建必要的 JNI绑定,正如 this question 中所述.
I'm trying to call Haskell code from Java, using JavaCPP to help create the necessary JNI binding, as already discussed in this question.
这就是我的使用方式:
<rootdir>
/javacpp.jar
/build (destination of libraris)
/src (contains Haskell code)
/com/example/HSCode.java (Java class to load and use native lib)
HScode.java
的内容:
package com.example;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
@Platform(include={"<HsFFI.h>","HScode_stub.h"})
public class HScode {
static { Loader.load(); }
public static native void hs_init(int[] argc, @Cast("char***") @ByPtrPtr PointerPointer argv);
public static native String code_hs(String text);
public static void main(String[] args) throws FileNotFoundException {
String s = new Scanner(new File("test.txt")).useDelimiter("\Z").next();
hs_init(null, null);
String s1 = code_hs(s);
System.out.println(s1);
}
}
编译:
cd <rootdir>
ghc --make -isrc -dynamic -shared -fPIC src/HScode.hs
-o build/libHScode.so -lHSrts-ghc7.8.4 -optl-Wl,-rpath,.
javac -cp javacpp.jar com/example/HScode.java
java -jar javacpp.jar -d build
-Dplatform.compiler=ghc -Dplatform.includepath="src:com/example"
-Dplatform.compiler.output="-optl-Wl,-rpath,. -optc-O3 -Wall build/libHScode.so -dynamic -fPIC -shared -lstdc++ -lHSrts-ghc7.8.4 -o " com.example.HScode
按照这种方法,我可以使用 javacpp
创建一个 libHScode.so
和一个 libjniHScode.so
,它们运行良好:
Following this approach, I can create a libHScode.so
and a libjniHScode.so
using javacpp
, which runs fine with:
$ java -cp javacpp.jar:. com.example.HScode
罐子
现在,接下来的步骤是我想将所有内容打包到一个 jar 中,并且能够从一个更大的 java 项目中使用这个 jar 的 com.example.HScode
.
JavaCPP 的页面提及:
JavaCPP's page mentions:
[...] 此外,在运行时,Loader.load() 方法会自动从 Java 资源中加载本地库,这些资源位于正确的目录由构建过程.它们甚至可以存档在 JAR 文件中,它不会改变任何内容.用户根本不需要图了解如何让系统加载文件.
[...] Moreover, at runtime, the Loader.load() method automatically loads the native libraries from Java resources, which were placed in the right directory by the building process. They can even be archived in a JAR file, it changes nothing. Users simply do not need to figure out how to make the system load the files.
所以我认为这应该可行.
So I thought this should work.
但是,如果我从上面 build
文件夹的内容中制作了一个 jar HScode.jar
,这样我的 jar 就同时包含 libjniHScode.so
和 libHScode.so
,然后运行它:
However, if I make a jar HScode.jar
out of the content of the build
folder above, so that my jar contains both libjniHScode.so
and libHScode.so
, and run it with:
$ java -cp javacpp.jar:HScode.jar:. com.example.HScode
然后它找不到我的本机代码(为匿名而编辑的异常):
then it cannot find my native code (exception edited for anonymization):
Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniHScode in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1865)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:597)
at org.bytedeco.javacpp.Loader.load(Loader.java:438)
at org.bytedeco.javacpp.Loader.load(Loader.java:381)
at com.example.HScode.<clinit>(HScode.java:13)
Caused by: java.lang.UnsatisfiedLinkError: /compilation-path/linux-x86_64/libjniHScode.so: HScode.so: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1937)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1822)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:580)
我错过了什么?有谁知道 JavaCPP 在 jar 中存档时是否真的可以找到本机代码?
What am I missing? Does anyone know whether JavaCPP can actually find the native code when it's archived in a jar?
推荐答案
通过调用 javacpp -jar javacpp.jar com.example.HScode
构建原生库,将它们输出到 com/example/linux-x86_64/
自动和 Loader
从那里加载它们.因此,当通过其他方式构建原生库时,如果我们想要 Loader
来找到它们.
Building for the native libraries by calling javacpp -jar javacpp.jar com.example.HScode
outputs them in com/example/linux-x86_64/
automatically and the Loader
loads them from there. So when building the native libraries by some other means, they still need to be moved to com/example/linux-x86_64/
, whether inside a JAR file or outside as normal files, if we want the Loader
to find them.
这篇关于JavaCPP,在 JAR 中归档本机库时出现 UnsatisfiedLinkError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!