Load multiple dependent libraries with JNA

后端 未结 2 2047
小蘑菇
小蘑菇 2021-01-07 10:52

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

相关标签:
2条回答
  • 2021-01-07 11:36

    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

    0 讨论(0)
  • 2021-01-07 11:42

    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");
    }
    
    0 讨论(0)
提交回复
热议问题