3 messages in net.java.dev.jna.users[jna-users] loading dynamic libraries...
FromSent OnAttachments
Filippo CaroneDec 12, 2008 2:36 pm.patch
Timothy WallDec 13, 2008 6:20 am 
Filippo CaroneDec 14, 2008 7:37 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:[jna-users] loading dynamic libraries in the global namespaceActions...
From:Filippo Carone (fili@carone.org)
Date:Dec 12, 2008 2:36:42 pm
List:net.java.dev.jna.users
Attachments:

Hi,

the attached patch allows users to specify if a given native library should be loaded in the global namespace.

Setting to Boolean.TRUE the Library.OPTION_DLOPEN_GLOBAL option in the options map argument given to Native.loadLibrary, will make jna to dlopen the library with the RTLD_GLOBAL option. For example:

Map options = new HashMap() { { put(Library.OPTION_DLOPEN_GLOBAL, Boolean.TRUE); } };

LibVlc INSTANCE = (LibVlc) Native.loadLibrary(Platform.isWindows()? "libvlc" : "vlc", LibVlc.class, options);

will make libvlc available in the global namespace of the java process, and so suitable for symbols resolution of shared objects loaded later (plugins for example).

Cheers, Filippo

Index: jnalib/native/dispatch.c =================================================================== --- jnalib/native/dispatch.c (revision 744) +++ jnalib/native/dispatch.c (working copy) @@ -63,6 +63,7 @@ #define LIBNAME2CSTR(ENV,JSTR) newCString(ENV,JSTR) #endif #define LOAD_LIBRARY(NAME) dlopen(NAME, RTLD_LAZY) +#define LOAD_LIBRARY_GLOBAL(NAME) dlopen(NAME, RTLD_LAZY|RTLD_GLOBAL) #define LOAD_ERROR(BUF,LEN) (snprintf(BUF, LEN, "%s", dlerror()), BUF) #define FREE_LIBRARY(HANDLE) dlclose(HANDLE) #define FIND_ENTRY(HANDLE, NAME) dlsym(HANDLE, NAME) @@ -634,15 +635,20 @@ /* * Class: com_sun_jna_NativeLibrary * Method: open - * Signature: (Ljava/lang/String;)J + * Signature: (Ljava/lang/String;Z)J */ JNIEXPORT jlong JNICALL -Java_com_sun_jna_NativeLibrary_open(JNIEnv *env, jclass cls, jstring lib){ +Java_com_sun_jna_NativeLibrary_open(JNIEnv *env, jclass cls, jstring lib,
jboolean global){ void *handle = NULL; LIBNAMETYPE libname = NULL;

if ((libname = LIBNAME2CSTR(env, lib)) != NULL) { - handle = (void *)LOAD_LIBRARY(libname); + if (!global) { + handle = (void *)LOAD_LIBRARY(libname); + } + else { + handle = (void *)LOAD_LIBRARY_GLOBAL(libname); + } if (!handle) { char buf[1024]; throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf))); Index: jnalib/src/com/sun/jna/NativeLibrary.java =================================================================== --- jnalib/src/com/sun/jna/NativeLibrary.java (revision 744) +++ jnalib/src/com/sun/jna/NativeLibrary.java (working copy) @@ -74,7 +74,7 @@ } }

- private static NativeLibrary loadLibrary(String libraryName) { + private static NativeLibrary loadLibrary(String libraryName, boolean
global) { List searchPath = new LinkedList();

// Append web start path, if available. Note that this does not @@ -103,7 +103,7 @@ // if it cannot find the library. // try { - handle = open(libraryPath); + handle = open(libraryPath, global); } catch(UnsatisfiedLinkError e) { // Add the system paths back for all fallback searching @@ -112,7 +112,7 @@ try { if (handle == 0) { libraryPath = findLibraryPath(libraryName, searchPath); - handle = open(libraryPath); + handle = open(libraryPath, global); } } catch(UnsatisfiedLinkError e) { @@ -122,7 +122,7 @@ // libraryPath = matchLibrary(libraryName, searchPath); if (libraryPath != null) { - try { handle = open(libraryPath); } + try { handle = open(libraryPath, global); } catch(UnsatisfiedLinkError e2) { e = e2; } } } @@ -131,14 +131,14 @@ libraryPath = "/System/Library/Frameworks/" + libraryName + ".framework/" + libraryName; if (new File(libraryPath).exists()) { - try { handle = open(libraryPath); } + try { handle = open(libraryPath, global); } catch(UnsatisfiedLinkError e2) { e = e2; } } } // Try the same library with a "lib" prefix else if (Platform.isWindows()) { libraryPath = findLibraryPath("lib" + libraryName, searchPath); - try { handle = open(libraryPath); } + try { handle = open(libraryPath, global); } catch(UnsatisfiedLinkError e2) { e = e2; } } if (handle == 0) { @@ -185,7 +185,7 @@ WeakReference ref = (WeakReference)libraries.get(libraryName); NativeLibrary library = ref != null ? (NativeLibrary)ref.get() :
null; if (library == null) { - library = loadLibrary(libraryName); + library = loadLibrary(libraryName, false); ref = new WeakReference(library); libraries.put(library.getName(), ref); libraries.put(library.getFile().getAbsolutePath(), ref); @@ -194,7 +194,43 @@ return library; } } + + /** + * Returns an instance of NativeLibrary for the specified name. + * The library is loaded if not already loaded. If already loaded, the + * existing instance is returned.<p> + * More than one name may map to the same NativeLibrary instance; only + * a single instance will be provided for any given unique file path. + * + * @param libraryName The library name to load. + * This can be short form (e.g. "c"), + * an explicit version (e.g. "libc.so.6"), or + * the full path to the library (e.g. "/lib/libc.so.6"). + * @param global If true, will load the library in the global namespace,
otherwise + * the library is loaded in the local namespace (as the default
behaviour). + */ + public static final NativeLibrary getInstance(String libraryName, boolean
global) { + if (!global) + { + return getInstance(libraryName); + } + if (libraryName == null) + throw new NullPointerException("Library name may not be null");

+ synchronized (libraries) { + WeakReference ref = (WeakReference)libraries.get(libraryName); + NativeLibrary library = ref != null ? (NativeLibrary)ref.get() :
null; + if (library == null) { + library = loadLibrary(libraryName, global); + ref = new WeakReference(library); + libraries.put(library.getName(), ref); + libraries.put(library.getFile().getAbsolutePath(), ref); + libraries.put(library.getFile().getName(), ref); + } + return library; + } + } + /** * Add a path to search for the specified library, ahead of any system
paths * @@ -470,7 +506,7 @@ return v; }

- private static native long open(String name); + private static native long open(String name, boolean global); private static native void close(long handle); private static native long findSymbol(long handle, String name); static { Index: jnalib/src/com/sun/jna/Library.java =================================================================== --- jnalib/src/com/sun/jna/Library.java (revision 744) +++ jnalib/src/com/sun/jna/Library.java (working copy) @@ -74,6 +74,10 @@ * be one of the predefined alignment types in {@link Structure}. */ String OPTION_STRUCTURE_ALIGNMENT = "structure-alignment"; + /** Option key for loading the library in the global namespace, specifing + * RTLD_GLOBAL option for dlopen() native call. + */ + String OPTION_DLOPEN_GLOBAL = "dlopen-global"; static class Handler implements InvocationHandler {

static final Method OBJECT_TOSTRING; @@ -119,8 +123,15 @@ throw new IllegalArgumentException("Invalid library name \"" + libname + "\""); } - - this.nativeLibrary = NativeLibrary.getInstance(libname); + Boolean dlopenGlobal = (Boolean)options.get(OPTION_DLOPEN_GLOBAL); + if (Boolean.TRUE.equals(dlopenGlobal)) + { + this.nativeLibrary = NativeLibrary.getInstance(libname, true); + } + else + { + this.nativeLibrary = NativeLibrary.getInstance(libname); + } this.interfaceClass = interfaceClass; this.options = options; this.callingConvention = Index: jnalib/build.xml =================================================================== --- jnalib/build.xml (revision 744) +++ jnalib/build.xml (working copy) @@ -39,10 +39,10 @@ <!-- jnidispatch library release version --> <property name="jni.major" value="3"/> <property name="jni.minor" value="0"/> - <property name="jni.revision" value="6"/> + <property name="jni.revision" value="7"/> <property name="jni.build" value="${build.number}"/> <property name="jni.version"
value="${jni.major}.${jni.minor}.${jni.revision}"/> - <property name="jni.md5" value="892beacd437514d23ed9b1cefeb2ead6"/> + <property name="jni.md5" value="8b5a20e7d71a719158113bb2ad97650e"/> <property name="spec.title" value="Java Native Access (JNA)"/> <property name="spec.vendor" value="${vendor}"/> <property name="spec.version" value="${jna.major}"/>