aboutsummaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2010-06-20 04:34:12 +0200
committerMichael Bien <[email protected]>2010-06-20 04:34:12 +0200
commitae37ac16a13aa62cd6e7a6ff0346403c5aa6b3e5 (patch)
tree13d7fd843bd0ea7de314c120513db94c79e01ffb /src/java
parent29072eee5784035d1284d3b9625450681fca25b3 (diff)
another round of ProcAddressTable refactoring.
- moved getAddressFor() from generated table to ProcAddressTable - added initEntry() to e.g. eagerly initialize one single entry (e.g. clGetExtensionFunctionAddress which must be available first) - several utility methods mostly usefull for debugging - cleanup
Diffstat (limited to 'src/java')
-rw-r--r--src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java177
-rwxr-xr-xsrc/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java76
2 files changed, 165 insertions, 88 deletions
diff --git a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
index f0be20f..6a73c0a 100644
--- a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
+++ b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
@@ -44,12 +44,35 @@ import java.io.PrintStream;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
/**
* Superclass for all generated ProcAddressTables.
+ *
+ * A ProcAddressTable is a cache of pointers to the dynamically-linkable C
+ * functions this autogenerated Java binding has exposed. Some
+ * libraries such as OpenGL, OpenAL and others define function pointer
+ * signatures rather than statically linkable entry points for the
+ * purposes of being able to query at run-time whether a particular
+ * extension is available. This table acts as a cache of these
+ * function pointers. Each function pointer is typically looked up at
+ * run-time by a platform-dependent mechanism such as dlsym(),
+ * wgl/glXGetProcAddress(), or alGetProcAddress(). If the field containing the function
+ * pointer is 0, the function is considered to be unavailable and can
+ * not be called.
+ *
* @author Kenneth Russel
* @author Michael Bien
* @author Sven Gothel
+ *
+ * @see FunctionAddressResolver
+ * @see DynamicLookupHelper
*/
public abstract class ProcAddressTable {
@@ -82,50 +105,31 @@ public abstract class ProcAddressTable {
this.resolver = resolver;
}
+
/**
- * Returns the address for the given function name.
- * @throws RuntimeException if the Table has not been initialized yet.
+ * Resets the complete table.
*/
- public abstract long getAddressFor(String functionName);
-
-
public void reset(DynamicLookupHelper lookup) throws RuntimeException {
+
if(null==lookup) {
throw new RuntimeException("Passed null DynamicLookupHelper");
}
- Class tableClass = getClass();
- Field[] fields = tableClass.getFields();
PrintStream dout = getDebugOutStream();
if (DEBUG) {
- dout.println("ProcAddressTable.reset(" + getClass().getName() + ")");
+ dout.println(getClass().getName()+".reset()");
}
- for (int i = 0; i < fields.length; ++i) {
- String addressFieldName = fields[i].getName();
- if (!addressFieldName.startsWith(PROCADDRESS_VAR_PREFIX)) {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = PROCADDRESS_VAR_PREFIX.length();
- String funcName = addressFieldName.substring(startOfMethodName);
- try {
- Field addressField = fields[i];
- assert (addressField.getType() == Long.TYPE);
-
- long newProcAddress = resolver.resolve(funcName, lookup);
- // set the current value of the proc address variable in the table object
- addressField.setLong(this, newProcAddress);
- if (DEBUG) {
- dout.println(" " + addressField.getName() + " -> 0x" + Long.toHexString(newProcAddress));
- }
- } catch (Exception e) {
- throw new RuntimeException("Can not get proc address for method \""
- + funcName + "\": Couldn't set value of field \"" + addressFieldName
- + "\" in class " + tableClass.getName(), e);
+ Field[] fields = getClass().getFields();
+ for (int i = 0; i < fields.length; ++i) {
+ String fieldName = fields[i].getName();
+ if (isAddressField(fieldName)) {
+ String funcName = fieldToFunctionName(fieldName);
+ setEntry(fields[i], funcName, lookup);
}
}
+
if (DEBUG) {
dout.flush();
if (DEBUG_PREFIX != null) {
@@ -134,6 +138,46 @@ public abstract class ProcAddressTable {
}
}
+ /**
+ * Initializes the mapping for a single function.
+ * @throws IllegalArgumentException if this function is not in this table.
+ */
+ public void initEntry(String name, DynamicLookupHelper lookup) {
+ Field field = fieldForFunction(name);
+ setEntry(field, name, lookup);
+ }
+
+ protected void setEntry(Field addressField, String funcName, DynamicLookupHelper lookup) {
+ try {
+ assert (addressField.getType() == Long.TYPE);
+ long newProcAddress = resolver.resolve(funcName, lookup);
+ // set the current value of the proc address variable in the table object
+ addressField.setLong(this, newProcAddress);
+ if (DEBUG) {
+ getDebugOutStream().println(" " + addressField.getName() + " -> 0x" + Long.toHexString(newProcAddress));
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Can not get proc address for method \""
+ + funcName + "\": Couldn't set value of field \"" + addressField, e);
+ }
+ }
+
+ protected String fieldToFunctionName(String addressFieldName) {
+ return addressFieldName.substring(PROCADDRESS_VAR_PREFIX.length());
+ }
+
+ protected Field fieldForFunction(String name) {
+ try {
+ return getClass().getField(PROCADDRESS_VAR_PREFIX + name);
+ } catch (NoSuchFieldException ex) {
+ throw new IllegalArgumentException(getClass().getName() +" has no entry for the function '"+name+"'.", ex);
+ }
+ }
+
+ protected boolean isAddressField(String fieldName) {
+ return fieldName.startsWith(PROCADDRESS_VAR_PREFIX);
+ }
+
protected static PrintStream getDebugOutStream() {
PrintStream out = null;
if (DEBUG) {
@@ -152,6 +196,79 @@ public abstract class ProcAddressTable {
return out;
}
+ /**
+ * Returns this table as map with the function name as key and the address as value.
+ */
+ public Map/*<String, Long>*/ toMap() {
+
+ SortedMap map = new TreeMap();
+
+ Field[] fields = getClass().getFields();
+ try {
+ for (int i = 0; i < fields.length; ++i) {
+ String addressFieldName = fields[i].getName();
+ if (isAddressField(addressFieldName)) {
+ map.put(fieldToFunctionName(addressFieldName), fields[i].get(this));
+ }
+ }
+ } catch (IllegalArgumentException ex) {
+ throw new RuntimeException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ return map;
+ }
+
+ /**
+ * Returns true only if non null function pointer to this function exists.
+ */
+ public boolean isFunctionAvailable(String functionName) {
+ try{
+ return getAddressFor(functionName) != 0;
+ }catch (IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
+ /**
+ * This is a convenience method to get (by name) the native function
+ * pointer for a given function. It lets you avoid having to
+ * manually compute the &quot;{@link #PROCADDRESS_VAR_PREFIX} + &lt;functionName&gt;&quot;
+ * member variable name and look it up via reflection.
+ *
+ * @throws IllegalArgumentException if this function is not in this table.
+ */
+ public long getAddressFor(String functionName) {
+ Field addressField = fieldForFunction(functionName);
+ try {
+ return addressField.getLong(this);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Returns all functions pointing to null.
+ */
+ public Set/*<String>*/ getNullPointerFunctions() {
+ Map table = toMap();
+ Set nullPointers = new LinkedHashSet();
+ for (Iterator it = table.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Entry) it.next();
+ long address = ((Long)entry.getValue()).longValue();
+ if(address == 0) {
+ nullPointers.add(entry.getKey());
+ }
+ }
+ return nullPointers;
+ }
+
+// @Override
+ public String toString() {
+ return getClass().getName()+""+toMap();
+ }
+
private static class One2OneResolver implements FunctionAddressResolver {
public long resolve(String name, DynamicLookupHelper lookup) {
diff --git a/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java b/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java
index aa71495..9094f14 100755
--- a/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java
+++ b/src/java/com/sun/gluegen/procaddress/ProcAddressEmitter.java
@@ -209,12 +209,16 @@ public class ProcAddressEmitter extends JavaEmitter {
}
protected void generateModifiedEmitters(CMethodBindingEmitter baseCEmitter, List<FunctionEmitter> emitters) {
+
+ FunctionSymbol cSymbol = baseCEmitter.getBinding().getCSymbol();
+
// 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());
+ boolean callThroughProcAddress = needsProcAddressWrapper(cSymbol);
+ boolean forceProcAddress = getProcAddressConfig().forceProcAddressGen(cSymbol.getName());
+
String forcedCallingConvention = null;
if (forceProcAddress) {
- forcedCallingConvention = getProcAddressConfig().getLocalProcAddressCallingConvention(baseCEmitter.getBinding().getCSymbol().getName());
+ forcedCallingConvention = getProcAddressConfig().getLocalProcAddressCallingConvention(cSymbol.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
@@ -223,11 +227,9 @@ 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,
- forceProcAddress,
- forcedCallingConvention,
- this);
+ ProcAddressCMethodBindingEmitter res = new ProcAddressCMethodBindingEmitter(
+ baseCEmitter, callThroughProcAddress, forceProcAddress, forcedCallingConvention, this);
+
MessageFormat exp = baseCEmitter.getReturnValueCapacityExpression();
if (exp != null) {
res.setReturnValueCapacityExpression(exp);
@@ -289,9 +291,7 @@ public class ProcAddressEmitter extends JavaEmitter {
if (implPackageName == null) {
implPackageName = getImplPackageName();
}
- String jImplRoot =
- getJavaOutputDir() + File.separator
- + CodeGenUtils.packageAsPath(implPackageName);
+ String jImplRoot = getJavaOutputDir() + File.separator + CodeGenUtils.packageAsPath(implPackageName);
tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java");
emittedTableEntries = new HashSet<String>();
@@ -303,24 +303,14 @@ public class ProcAddressEmitter extends JavaEmitter {
for (String imporT : getConfig().imports()) {
tableWriter.println("import " + imporT + ";");
}
+ tableWriter.println("import " + ProcAddressTable.class.getName() + ";");
tableWriter.println();
tableWriter.println("/**");
- tableWriter.println(" * This table is a cache of pointers to the dynamically-linkable C");
- tableWriter.println(" * functions this autogenerated Java binding has exposed. Some");
- tableWriter.println(" * libraries such as OpenGL, OpenAL and others define function pointer");
- tableWriter.println(" * signatures rather than statically linkable entry points for the");
- tableWriter.println(" * purposes of being able to query at run-time whether a particular");
- tableWriter.println(" * extension is available. This table acts as a cache of these");
- tableWriter.println(" * function pointers. Each function pointer is typically looked up at");
- tableWriter.println(" * run-time by a platform-dependent mechanism such as dlsym(),");
- tableWriter.println(" * wgl/glXGetProcAddress(), or alGetProcAddress(). The associated");
- tableWriter.println(" * autogenerated Java and C code accesses the fields in this table to");
- tableWriter.println(" * call the various functions. If the field containing the function");
- tableWriter.println(" * pointer is 0, the function is considered to be unavailable and can");
- tableWriter.println(" * not be called.");
+ tableWriter.println(" * This table is a cache of pointers to the dynamically-linkable C library.");
+ tableWriter.println(" * @see " + ProcAddressTable.class.getSimpleName());
tableWriter.println(" */");
- tableWriter.println("public class " + tableClassName + " extends "+ ProcAddressTable.class.getName() + " {");
+ tableWriter.println("public class " + tableClassName + " extends "+ ProcAddressTable.class.getSimpleName() + " {");
tableWriter.println();
for (String string : getProcAddressConfig().getForceProcAddressGen()) {
@@ -336,39 +326,9 @@ public class ProcAddressEmitter extends JavaEmitter {
}
protected void endProcAddressTable() throws Exception {
- PrintWriter w = tableWriter;
-
- w.println(" /**");
- w.println(" * This is a convenience method to get (by name) the native function");
- w.println(" * pointer for a given function. It lets you avoid having to");
- w.println(" * manually compute the &quot;" + PROCADDRESS_VAR_PREFIX + " + ");
- w.println(" * &lt;functionName&gt;&quot; member variable name and look it up via");
- w.println(" * reflection; it also will throw an exception if you try to get the");
- w.println(" * address of an unknown function, or one that is statically linked");
- w.println(" * and therefore does not have a function pointer in this table.");
- w.println(" *");
- w.println(" * @throws RuntimeException if the function pointer was not found in");
- w.println(" * this table, either because the function was unknown or because");
- w.println(" * it was statically linked.");
- w.println(" */");
- w.println(" public long getAddressFor(String functionName) {");
- w.println(" String addressFieldName = PROCADDRESS_VAR_PREFIX + functionName;");
- w.println(" try { ");
- w.println(" java.lang.reflect.Field addressField = getClass().getField(addressFieldName);");
- w.println(" return addressField.getLong(this);");
- w.println(" } catch (Exception e) {");
- w.println(" // The user is calling a bogus function or one which is not");
- w.println(" // runtime linked");
- w.println(" throw new RuntimeException(");
- w.println(" \"WARNING: Address query failed for \\\"\" + functionName +");
- w.println(" \"\\\"; it's either statically linked or is not a known \" +");
- w.println(" \"function\", e);");
- w.println(" } ");
- w.println(" }");
-
- w.println("} // end of class " + tableClassName);
- w.flush();
- w.close();
+ tableWriter.println("} // end of class " + tableClassName);
+ tableWriter.flush();
+ tableWriter.close();
}
protected void emitProcAddressTableEntryForString(String str) {