Is there a way in JNA to load multiple dependent libraries with Java?
I usually use Native.loadLibrary(...)
to load one DLL. But I guess its not workin
Loading lib transient dependencies with JNA from JAR Resources.
My resources folder res:
res/
`-- linux-x86-64
|-- libapi.so
|-- libdependency.so
-
MyApiLibrary api = (MyApiLibrary) Native.loadLibrary("libapi.so", MyApiLibrary.class, options);
API Explodes: Caused by: java.lang.UnsatisfiedLinkError: Error loading shared library libdependency.so: No such file or directory
Can be solved by loading dependencies beforehand by hand:
import com.sun.jna.Library;
Native.loadLibrary("libdependency.so", Library.class);
MyApiLibrary api = (MyApiLibrary) Native.loadLibrary("libapi.so", MyApiLibrary.class, options);
Basically you have to build dependency tree in reverse, by hand, by yourself.
I recommend setting
java -Djna.debug_load=true -Djna.debug_load.jna=true
Furthermore, setting jna.library.path to Resource has no effect, because JNA extracts to filesystem, then it loads lib. Lib on filesystem can NOT access other libs within jar.
Context class loader classpath. Deployed native libraries may be installed on the classpath under ${os-prefix}/LIBRARY_FILENAME, where ${os-prefix} is the OS/Arch prefix returned by Platform.getNativeLibraryResourcePrefix(). If bundled in a jar file, the resource will be extracted to jna.tmpdir for loading, and later removed (but only if jna.nounpack is false or not set).
Javadoc
RTFM and happy coding. JNA v.4.1.0
Let's say I have library foo
and library bar
. bar
has a dependency on foo
; it also has a dependency on baz
, which we are not mapping with JNA:
public class Foo {
public static final boolean LOADED;
static {
Native.register("foo");
LOADED = true;
}
public static native void call_foo();
}
public class Bar {
static {
// Reference "Foo" so that it is loaded first
if (Foo.LOADED) {
System.loadLibrary("baz");
// Or System.load("/path/to/libbaz.so")
Native.register("bar");
}
}
public static native void call_bar();
}
The call to System.load/loadLibrary
will only be necessary if baz
is neither on your library load path (PATH
/LD_LIBRARY_PATH
, for windows/linux respectively) nor in the same directory as bar
(windows only).
EDIT
You can also do this via interface mapping:
public interface Foo extends Library {
Foo INSTANCE = (Foo)Native.loadLibrary("foo");
}
public interface Bar extends Library {
// Reference Foo prior to instantiating Bar, just be sure
// to reference the Foo class prior to creating the Bar instance
Foo FOO = Foo.INSTANCE;
Bar INSTANCE = (Bar)Native.loadLibrary("bar");
}