如何在不获取UnsatifiedLinkError的情况下加载具有依赖项的JNI .dylib文件? [英] How to load a JNI .dylib file with a dependency without getting an UnsatifiedLinkError?

查看:178
本文介绍了如何在不获取UnsatifiedLinkError的情况下加载具有依赖项的JNI .dylib文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:将Java链接到Swift

Goal: Link Java to Swift

问题:我得到一个.dylib文件链接的JNI .dylib文件时,noreferrer> UnsatisfiedLinkError /docs/api/java/lang/System.html#loadLibrary(java.lang.String)"rel =" nofollow noreferrer> System#loadLibrary(String) .

Problem: I get an UnsatisfiedLinkError when trying to load a JNI .dylib file that is linked with a Swift .dylib file when calling System#loadLibrary(String).

预期的行为: Java .dylib的依赖项将被自动加载,或者对System.loadLibrary("SwiftCode")的调用将加载该依赖项(我唯一能想到的解决方案).

Expected Behavior: The dependency of the Java .dylib would be automatically loaded or the call to System.loadLibrary("SwiftCode") would load the dependency (the only solution I could come up with).

注意::我将此github教程这篇中等文章创建我的JNI .dylib文件,并本教程创建我的Swift 文件.

Note: I am combining this github tutorial and this Medium article to create my JNI .dylib file and this tutorial to create my Swift .dylib file.

完整的堆栈跟踪:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/hillmacbookpro/IdeaProjects/JavaToSwift/src/native/libSwiftHelloWorld.dylib: dlopen(/Users/hillmacbookpro/IdeaProjects/JavaToSwift/src/native/libSwiftHelloWorld.dylib, 1): Library not loaded: libSwiftCode.dylib
  Referenced from: /Users/hillmacbookpro/IdeaProjects/JavaToSwift/src/native/libSwiftHelloWorld.dylib
  Reason: image not found
    at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
    at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2408)
    at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2465)
    at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2662)
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2627)
    at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
    at java.base/java.lang.System.loadLibrary(System.java:1833)
    at helloworld.SwiftHelloWorld.<clinit>(SwiftHelloWorld.java:7)

文件结构:

src
  - helloworld
      - SwiftHelloWorld.java
  - native
      - libSwiftHelloWorld.dylib
      - libSwiftCode.dylib

MCVE:

SwiftHelloWorld.java:

package helloworld;

public class SwiftHelloWorld {

    static {
        System.loadLibrary("SwiftCode"); // loading SwiftHelloWorld's dependency first
        System.loadLibrary("SwiftHelloWorld"); // exception thrown here, can't find dependency?
    }

    public static native void printHelloWorldImpl();

    public static void main(final String[] args) {
        printHelloWorldImpl();
    }

}

libSwiftHelloWorld.dylib:使用以下两个终端命令创建:

libSwiftHelloWorld.dylib: Created using these two terminal commands:

export JAVA_HOME="$(/usr/libexec/java_home -v 11)"; gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSwiftHelloWorld.dylib -dynamiclib helloworld_SwiftHelloWorld.c libSwiftCode.dylib

和这些文件:

  • helloworld_SwiftHelloWorld.c:

#include <jni.h>
#include <stdio.h>
#include "helloworld_SwiftHelloWorld.h"
#include "helloworld_SwiftHelloWorld_swift.h"

JNIEXPORT void JNICALL Java_helloworld_SwiftHelloWorld_printHelloWorldImpl
  (JNIEnv *env, jclass clazz) {

    int result = swiftHelloWorld(42);
    printf("%s%i%s", "Hello World from JNI! ", result, "\n");

}

  • helloworld_SwiftHelloWorld.h:从以下位置自动生成的JNI标头 javac -h native/ helloworld/SwiftHelloWorld.java

  • helloworld_SwiftHelloWorld.h: The auto-generated JNI header from javac -h native/ helloworld/SwiftHelloWorld.java

    helloworld_SwiftHelloWorld_swift.h:

    int swiftHelloWorld(int);
    

  • libSwiftCode.dylib:使用swiftc SwiftCode.swift -emit-library -o libSwiftCode.dylibSwiftCode.swift文件创建:

    import Foundation
    
    // force the function to have a name callable by the c code
    @_silgen_name("swiftHelloWorld")
    public func swiftHelloWorld(number: Int) -> Int {
        print("Hello world from Swift: \(number)")
        return 69
    }
    

    相关问题:

    • Java JNI linking multiple libraries, he/she gets an UnsatifiedLinkError but with the discription undefined symbol: ... (unanswered)

    标记有JNI并且包含UnsatifiedLinkError

    其他说明:我将Java虚拟机的选项设置为-Djava.library.path=src/native,这是两个.dylib文件的父目录.我正在使用macOS.

    Other Notes: I am setting the Java virtual machine's options to -Djava.library.path=src/native, the parent directory of both of the .dylib files. I am using macOS.

    我已经尝试在命令前使用xcrun编译SwiftCode.swift,如

    I have tried preceding the command to compile SwiftCode.swift with xcrun as seen in this article (under "Compile Swift code") but I still get the same error.

    推荐答案

    macOS ld将库依赖项的路径构建为二进制文件.加载libSwiftHelloWorld.dylib的加载程序仅在libSwiftCode.dylib在当前目录中时才能找到它.在Java中加载依赖项无效,因为对于加载器来说,它是一个不同的库.

    macOS ld builds a library dependency's path into the binary. The loader loading libSwiftHelloWorld.dylib will only find libSwiftCode.dylib if the latter is in the current directory. Loading the dependency in Java doesn't work because for the loader it's a different library.

    您可以使用-install_name参数(即swiftc ... -Xlinker -install_name -Xlinker <your path>)更改libSwiftCode.dylib的内置路径.如果之后重建libSwiftHelloWorld.dylib,它将引用您给出的路径.

    You can change the built-in path for libSwiftCode.dylib with the -install_name argument (i.e. swiftc ... -Xlinker -install_name -Xlinker <your path>). If you rebuild libSwiftHelloWorld.dylib afterwards it will reference the path that you gave.

    这篇关于如何在不获取UnsatifiedLinkError的情况下加载具有依赖项的JNI .dylib文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆