如何在不获取UnsatifiedLinkError的情况下加载具有依赖项的JNI .dylib文件? [英] How to load a JNI .dylib file with a dependency without getting an UnsatifiedLinkError?
问题描述
目标:将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.dylib
和SwiftCode.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 ,他/她得到一个
UnsatifiedLinkError
,但标题为undefined symbol: ...
(未回答)
Java JNI linking multiple libraries, he/she gets an
UnsatifiedLinkError
but with the discriptionundefined 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屋!