diff options
6 files changed, 91 insertions, 15 deletions
diff --git a/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java b/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java index 423f009..8dc46ee 100755 --- a/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java +++ b/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java @@ -46,12 +46,14 @@ import com.sun.gluegen.cgram.types.*; public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { private boolean callThroughProcAddress; + private boolean needsLocalTypedef; private static String procAddressJavaTypeName = JavaType.createForClass(Long.TYPE).jniTypeName(); private ProcAddressEmitter emitter; public ProcAddressCMethodBindingEmitter(CMethodBindingEmitter methodToWrap, final boolean callThroughProcAddress, + boolean needsLocalTypedef, ProcAddressEmitter emitter) { super( new MethodBinding(methodToWrap.getBinding()) { @@ -91,6 +93,7 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { setCommentEmitter(defaultCommentEmitter); this.callThroughProcAddress = callThroughProcAddress; + this.needsLocalTypedef = needsLocalTypedef; this.emitter = emitter; } @@ -112,10 +115,24 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { protected void emitBodyVariableDeclarations(PrintWriter writer) { if (callThroughProcAddress) { // create variable for the function pointer with the right type, and set - // it to the value of the passed-in glProcAddress + // it to the value of the passed-in proc address FunctionSymbol cSym = getBinding().getCSymbol(); String funcPointerTypedefName = emitter.getFunctionPointerTypedefName(cSym); + + if (needsLocalTypedef) { + // We (probably) didn't get a typedef for this function + // pointer type in the header file; the user requested that we + // forcibly generate one. Here we force the emission of one. + PointerType funcPtrType = new PointerType(null, cSym.getType(), 0); + // Just for safety, emit this name slightly differently than + // the mangling would otherwise produce + funcPointerTypedefName = "_local_" + funcPointerTypedefName; + + writer.print(" typedef "); + writer.print(funcPtrType.toString(funcPointerTypedefName)); + writer.println(";"); + } writer.print(" "); writer.print(funcPointerTypedefName); diff --git a/src/java/com/sun/gluegen/procaddress/ProcAddressConfiguration.java b/src/java/com/sun/gluegen/procaddress/ProcAddressConfiguration.java index 54dd2cb..e5edd0d 100755 --- a/src/java/com/sun/gluegen/procaddress/ProcAddressConfiguration.java +++ b/src/java/com/sun/gluegen/procaddress/ProcAddressConfiguration.java @@ -52,6 +52,7 @@ public class ProcAddressConfiguration extends JavaConfiguration private String tableClassName = "ProcAddressTable"; private Set/*<String>*/ skipProcAddressGen = new HashSet(); private List/*<String>*/ forceProcAddressGen = new ArrayList(); + private Set/*<String>*/ forceProcAddressGenSet = new HashSet(); private String getProcAddressTableExpr; private ConvNode procAddressNameConverter; @@ -78,6 +79,7 @@ public class ProcAddressConfiguration extends JavaConfiguration { String sym = readString("ForceProcAddressGen", tok, filename, lineNo); forceProcAddressGen.add(sym); + forceProcAddressGenSet.add(sym); } else if (cmd.equalsIgnoreCase("GetProcAddressTableExpr")) { @@ -253,4 +255,7 @@ public class ProcAddressConfiguration extends JavaConfiguration return procAddressNameConverter.convert(funcName); } + public boolean forceProcAddressGen(String funcName) { + return forceProcAddressGenSet.contains(funcName); + } } diff --git a/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java b/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java index 75fb59c..19d4fe3 100755 --- a/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java +++ b/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java @@ -58,6 +58,7 @@ public class ProcAddressEmitter extends JavaEmitter protected static final String WRAP_PREFIX = "dispatch_"; private TypeDictionary typedefDictionary; private PrintWriter tableWriter; + private Set emittedTableEntries; private String tableClassPackage; private String tableClassName; @@ -219,6 +220,7 @@ public class ProcAddressEmitter extends JavaEmitter { // See whether we need a proc address entry for this one boolean callThroughProcAddress = needsProcAddressWrapper(baseCEmitter.getBinding().getCSymbol()); + boolean forceProcAddress = getProcAddressConfig().forceProcAddressGen(baseCEmitter.getBinding().getCSymbol().getName()); // Note that we don't care much about the naming of the C argument // variables so to keep things simple we ignore the buffer object // property for the binding @@ -226,7 +228,10 @@ public class ProcAddressEmitter extends JavaEmitter // The C-side JNI binding for this particular function will have an // extra final argument, which is the address (the OpenGL procedure // address) of the function it needs to call - ProcAddressCMethodBindingEmitter res = new ProcAddressCMethodBindingEmitter(baseCEmitter, callThroughProcAddress, this); + ProcAddressCMethodBindingEmitter res = new ProcAddressCMethodBindingEmitter(baseCEmitter, + callThroughProcAddress, + forceProcAddress, + this); MessageFormat exp = baseCEmitter.getReturnValueCapacityExpression(); if (exp != null) { res.setReturnValueCapacityExpression(exp); @@ -250,6 +255,10 @@ public class ProcAddressEmitter extends JavaEmitter shouldWrap = false; } + if (config.forceProcAddressGen(symName)) { + shouldWrap = true; + } + if (shouldWrap) { // Hoist argument names from function pointer if not supplied in prototype @@ -281,6 +290,7 @@ public class ProcAddressEmitter extends JavaEmitter CodeGenUtils.packageAsPath(implPackageName); tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java"); + emittedTableEntries = new HashSet(); CodeGenUtils.emitAutogeneratedWarning(tableWriter, this); @@ -358,6 +368,11 @@ public class ProcAddressEmitter extends JavaEmitter protected void emitProcAddressTableEntryForString(String str) { + // Deal gracefully with forced proc address generation in the face + // of having the function pointer typedef in the header file too + if (emittedTableEntries.contains(str)) + return; + emittedTableEntries.add(str); tableWriter.print(" public long "); tableWriter.print(PROCADDRESS_VAR_PREFIX); tableWriter.print(str); diff --git a/src/java/com/sun/gluegen/runtime/MacOSXDynamicLinkerImpl.java b/src/java/com/sun/gluegen/runtime/MacOSXDynamicLinkerImpl.java index 37e3cd0..f998d07 100755 --- a/src/java/com/sun/gluegen/runtime/MacOSXDynamicLinkerImpl.java +++ b/src/java/com/sun/gluegen/runtime/MacOSXDynamicLinkerImpl.java @@ -34,7 +34,7 @@ public class MacOSXDynamicLinkerImpl implements DynamicLinker // other words, one can actually link against the library instead of // having to dlsym all entry points. System.loadLibrary() uses // RTLD_LOCAL visibility so can't be used for this purpose. - return dlopen(pathname, RTLD_GLOBAL); + return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL); } public long lookupSymbol(long libraryHandle, String symbolName) { diff --git a/src/java/com/sun/gluegen/runtime/NativeLibrary.java b/src/java/com/sun/gluegen/runtime/NativeLibrary.java index f61afb6..01148b1 100755 --- a/src/java/com/sun/gluegen/runtime/NativeLibrary.java +++ b/src/java/com/sun/gluegen/runtime/NativeLibrary.java @@ -61,6 +61,7 @@ public class NativeLibrary { private static final int WINDOWS = 1; private static final int UNIX = 2; private static final int MACOSX = 3; + private static boolean DEBUG; private static int platform; private static DynamicLinker dynLink; private static String prefix; @@ -78,6 +79,9 @@ public class NativeLibrary { } else { platform = UNIX; } + + DEBUG = (System.getProperty("gluegen.debug.NativeLibrary") != null); + return null; } }); @@ -118,35 +122,58 @@ public class NativeLibrary { } /** Opens the given native library, assuming it has the same base - name on all platforms, in the context of the specified - ClassLoader, which is used to help find the library in the case - of e.g. Java Web Start. */ + name on all platforms, looking first in the system's search + path, and in the context of the specified ClassLoader, which is + used to help find the library in the case of e.g. Java Web Start. */ public static NativeLibrary open(String libName, ClassLoader loader) { - return open(libName, libName, libName, loader); + return open(libName, libName, libName, true, loader); } /** Opens the given native library, assuming it has the given base names (no "lib" prefix or ".dll/.so/.dylib" suffix) on the Windows, Unix and Mac OS X platforms, respectively, and in the context of the specified ClassLoader, which is used to help find - the library in the case of e.g. Java Web Start. */ + the library in the case of e.g. Java Web Start. The + searchSystemPathFirst argument changes the behavior to first + search the default system path rather than searching it last. + Note that we do not currently handle DSO versioning on Unix. + Experience with JOAL and OpenAL has shown that it is extremely + problematic to rely on a specific .so version (for one thing, + ClassLoader.findLibrary on Unix doesn't work with files not + ending in .so, for example .so.0), and in general if this + dynamic loading facility is used correctly the version number + will be irrelevant. + */ public static NativeLibrary open(String windowsLibName, String unixLibName, String macOSXLibName, + boolean searchSystemPathFirst, ClassLoader loader) { List possiblePaths = enumerateLibraryPaths(windowsLibName, unixLibName, macOSXLibName, + searchSystemPathFirst, loader); // Iterate down these and see which one if any we can actually find. for (Iterator iter = possiblePaths.iterator(); iter.hasNext(); ) { String path = (String) iter.next(); + if (DEBUG) { + System.out.println("Trying to load " + path); + } ensureNativeLibLoaded(); long res = dynLink.openLibrary(path); if (res != 0) { + if (DEBUG) { + System.out.println("Successfully loaded " + path + ": res = 0x" + Long.toHexString(res)); + } return new NativeLibrary(res, path); } } + + if (DEBUG) { + System.out.println("Did not succeed in loading (" + windowsLibName + ", " + unixLibName + ", " + macOSXLibName + ")"); + } + // For now, just return null to indicate the open operation didn't // succeed (could also throw an exception if we could tell which // of the openLibrary operations actually failed) @@ -188,18 +215,28 @@ public class NativeLibrary { private static List enumerateLibraryPaths(String windowsLibName, String unixLibName, String macOSXLibName, + boolean searchSystemPathFirst, ClassLoader loader) { + List paths = new ArrayList(); String libName = selectName(windowsLibName, unixLibName, macOSXLibName); + if (libName == null) + return paths; String[] baseNames = buildNames(libName); - List paths = new ArrayList(); + if (searchSystemPathFirst) { + // Add just the library names to use the OS's search algorithm + for (int i = 0; i < baseNames.length; i++) { + paths.add(baseNames[i]); + } + } // The idea to ask the ClassLoader to find the library is borrowed // from the LWJGL library String clPath = getPathFromClassLoader(libName, loader); - if (clPath != null) + if (clPath != null) { paths.add(clPath); - + } + // Add entries from java.library.path String javaLibraryPath = (String) AccessController.doPrivileged(new PrivilegedAction() { @@ -223,9 +260,11 @@ public class NativeLibrary { }); addPaths(userDir, baseNames, paths); - // Add just the library names to use the OS's search algorithm - for (int i = 0; i < baseNames.length; i++) { - paths.add(baseNames[i]); + if (!searchSystemPathFirst) { + // Add just the library names to use the OS's search algorithm + for (int i = 0; i < baseNames.length; i++) { + paths.add(baseNames[i]); + } } return paths; diff --git a/src/java/com/sun/gluegen/runtime/UnixDynamicLinkerImpl.java b/src/java/com/sun/gluegen/runtime/UnixDynamicLinkerImpl.java index 006f90d..b6a79be 100755 --- a/src/java/com/sun/gluegen/runtime/UnixDynamicLinkerImpl.java +++ b/src/java/com/sun/gluegen/runtime/UnixDynamicLinkerImpl.java @@ -40,7 +40,7 @@ public class UnixDynamicLinkerImpl implements DynamicLinker // other words, one can actually link against the library instead of // having to dlsym all entry points. System.loadLibrary() uses // RTLD_LOCAL visibility so can't be used for this purpose. - return dlopen(pathname, RTLD_GLOBAL); + return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL); } public long lookupSymbol(long libraryHandle, String symbolName) { |