将 SmartID Reader JNI 库添加到现有 gradle 项目中

Add SmartID Reader JNI library into existing gradle project

我正在尝试在现有项目中使用 Smart IDReader SDK 试用版 (https://habr.com/en/company/smartengines/blog/332670/) Gradle(项目组装到 war-archive)。 应用程序工作站是 centOS,我不需要支持本机库的所有体系结构。所以,我有 libjniSmartIdEngine.so 本机库和 jniSmartIdEngineJar.jar。同样在 SDK c++ *.h 文件和 *java SWIG classes 中出现。 我在尝试什么:

  1. 在 /resources/ 中添加 jar 和 so 库。
  2. 在build.gradle依赖项中添加编译文件('lib/jniSmartIdEngineJar.jar','libjniSmartIdEngine.so')。
  3. 在我的 class 我想使用提供的示例代码的静态块中加载资源。

    静态{ URL jniWrapper = SmartIDReader.class.getResource("/res/jniSmartIdEngineJar.jar"); System.load(jniWrapper.getPath()); }

Jar 和 So 放在同一个文件夹中,我有错误:

It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.Exception in thread "main" java.lang.UnsatisfiedLinkError: /jniSmartIdEngineJar.jar: /jniSmartIdEngineJar.jar: invalid ELF header (Possible cause: endianness mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)

我所需要的一切 - 这就是在我的项目中正确初始化库,但我不明白如何。 我找到了一些解决方案: * Correct way to add external jars (lib/*.jar) to an IntelliJ IDEA project 建议在项目结构中手动添加依赖项(但是当我像上面描述的那样通过 gradle 添加它时,库已经存在)/ * How to bundle a native library and a JNI library inside a JAR? 和此处建议的 jar,而不是 war。如果我理解正确,我不需要将库解压缩到临时文件并加载它。

这是库的转轮:

javac *.java -cp ../../bindings/java/jniSmartIdEngineJar.jar

for image in ../../testdata/*; do 
  config=$(ls ../../data-zip/*.zip) # assuming one file
  for document_types in "rus.passport.*" "mrz.*" "rus.drvlic.*" "*"; do
    LD_LIBRARY_PATH=../../bin LC_ALL=en_US.utf-8 java -cp ../../bindings/java/jniSmartIdEngineJar.jar:. Main "$image" "$config" "$document_types"
  done
done

请解释我如何在我的项目中使用该外部 JNI 库。以及如何用 gradle 配置替换 shell 跑步者。

PS.: 我正在研究 Ubuntu 并且 shell 运行正常。我做错了什么?

找到解决方案:

  1. 要加载外部 JNI 库,必须将其添加到项目文件夹中(例如 /lib/)
  2. JAR 包装文件(在我的例子中生成的 swig)必须添加为依赖项(右键单击 jar > 添加为库或在项目结构模块依赖项中手动添加)。在我的例子中,我使用 gradle

        compile fileTree(include: ['*.jar'], dir: 'lib')
    

    在依赖项 {} 块中

  3. 之后,来自 jar 的 类 将在项目中可用,并且我们需要的一切 - 添加本机库。有几种方法:设置 -Djava.library.path=... 作为 JVM 运行 参数,或者像下面描述的那样动态配置它: https://habr.com/en/post/118027/ 另一种方法 - 只需将库放在系统文件夹中或在系统变量中添加新目录(路径 Windows 或 LD_LIBRARY_PATH linux)。此处解释:How should I load native libraries for JNI to avoid an UnsatisfiedLinkError?

关于 shell 脚本:在 p.1 中,我们在类路径中添加了 jar-wrapper LD_LIBRARY_PATH 必须指定 linux 或其他描述的解决方案,jvm 将能够在其中找到本机库。

最后一个 - SmartId Reader 没有 ubuntu sdk,所以 centOS 软件包无法在 ubuntu 上运行(jvm SIGSEGV 错误,有问题的框架:ld-linux-x86-64.so)。我只是使用 windows sdk,它解决了问题。