From 57571086dabbaccebac3dcf8dc3cf41841bd4159 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Thu, 10 Jun 2010 17:12:52 +0200 Subject: refactored Platform. Simplified initializer. --- src/java/com/jogamp/common/os/Platform.java | 76 ++++++++++++++++------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java index b6298a7..0d8b276 100644 --- a/src/java/com/jogamp/common/os/Platform.java +++ b/src/java/com/jogamp/common/os/Platform.java @@ -34,20 +34,21 @@ import com.jogamp.common.nio.Buffers; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; -import java.security.*; /** * Utility class for querying platform specific properties. - * @author Michael Bien, Sven Gothel + * @author Michael Bien + * @author Sven Gothel */ public class Platform { public static final boolean JAVA_SE; public static final boolean LITTLE_ENDIAN; + public static final String OS; + public static final String ARCH; - private final static boolean is32Bit; - private final static int pointerSizeInBits; - private final static String os, arch; + private static final boolean is32Bit; + private static final int pointerSizeInBits; static { NativeLibrary.ensureNativeLibLoaded(); @@ -55,17 +56,24 @@ public class Platform { // We don't seem to need an AccessController.doPrivileged() block // here as these system properties are visible even to unsigned // applets - os = System.getProperty("os.name"); - arch = System.getProperty("os.arch"); + OS = System.getProperty("os.name"); + ARCH = System.getProperty("os.arch"); pointerSizeInBits = getPointerSizeInBitsImpl(); + is32Bit = initAch(); + JAVA_SE = initIsJavaSE(); + LITTLE_ENDIAN = initByteOrder(); + } + + private Platform() {} - // Try to use Sun's sun.arch.data.model first .. + private static boolean initAch() throws RuntimeException { + // Try to use Sun's sun.ARCH.data.model first .. if ( 32 == pointerSizeInBits || 64 == pointerSizeInBits ) { - is32Bit = ( 32 == pointerSizeInBits ); + return 32 == pointerSizeInBits; }else { - String os_lc = os.toLowerCase(); - String arch_lc = arch.toLowerCase(); + String os_lc = OS.toLowerCase(); + String arch_lc = ARCH.toLowerCase(); if ((os_lc.startsWith("windows") && arch_lc.equals("x86")) || (os_lc.startsWith("windows") && arch_lc.equals("arm")) || @@ -79,7 +87,7 @@ public class Platform { (os_lc.startsWith("sunos_lc") && arch_lc.equals("x86")) || (os_lc.startsWith("freebsd") && arch_lc.equals("i386")) || (os_lc.startsWith("hp-ux") && arch_lc.equals("pa_risc2.0"))) { - is32Bit = true; + return true; } else if ((os_lc.startsWith("windows") && arch_lc.equals("amd64")) || (os_lc.startsWith("linux") && arch_lc.equals("amd64")) || (os_lc.startsWith("linux") && arch_lc.equals("x86_64")) || @@ -88,44 +96,41 @@ public class Platform { (os_lc.startsWith("darwin") && arch_lc.equals("x86_64")) || (os_lc.startsWith("sunos_lc") && arch_lc.equals("sparcv9")) || (os_lc.startsWith("sunos_lc") && arch_lc.equals("amd64"))) { - is32Bit = false; + return false; }else{ throw new RuntimeException("Please port CPU detection (32/64 bit) to your platform (" + os_lc + "/" + arch_lc + ")"); } } + } + + private static boolean initIsJavaSE() { + + // fast path for desktop + if(System.getSecurityManager() == null && System.getProperty("java.runtime.name").indexOf("Java SE") != -1) { + return true; + } - boolean se; + // probe for classes we need on a SE environment try{ Class.forName("java.nio.LongBuffer"); Class.forName("java.nio.DoubleBuffer"); - se = true; + return true; }catch(ClassNotFoundException ex) { - se = false; + return false; } + } - if(!se) { - // no more the fast path, due to access controller .. - String java_runtime_name = (String) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - return System.getProperty("java.runtime.name"); - } - }); - se = java_runtime_name.indexOf("Java SE") != -1; - } - JAVA_SE = se; - - // byte order + private static boolean initByteOrder() { ByteBuffer tst_b = Buffers.newDirectByteBuffer(Buffers.SIZEOF_INT); // 32bit in native order IntBuffer tst_i = tst_b.asIntBuffer(); ShortBuffer tst_s = tst_b.asShortBuffer(); tst_i.put(0, 0x0A0B0C0D); - LITTLE_ENDIAN = 0x0C0D == tst_s.get(0); + return 0x0C0D == tst_s.get(0); } - private Platform() {} - private static native int getPointerSizeInBitsImpl(); + /** * Returns true only if this program is running on the Java Standard Edition. */ @@ -144,14 +149,14 @@ public class Platform { * Returns the OS name. */ public static String getOS() { - return os; + return OS; } /** * Returns the CPU architecture String. */ public static String getArch() { - return arch; + return ARCH; } /** @@ -165,6 +170,9 @@ public class Platform { return pointerSizeInBits; } -} + public static int getPointerSizeInBytes() { + return pointerSizeInBits/8; + } +} -- cgit v1.2.3 From c6748a9901ed4bb0de1d4f844637beb76477af65 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Thu, 10 Jun 2010 17:17:58 +0200 Subject: currently no need for a (public) MiscUtils.java. --- .../com/jogamp/common/os/DynamicLibraryBundle.java | 14 +++--- src/java/com/jogamp/common/util/MiscUtils.java | 57 ---------------------- 2 files changed, 6 insertions(+), 65 deletions(-) delete mode 100644 src/java/com/jogamp/common/util/MiscUtils.java diff --git a/src/java/com/jogamp/common/os/DynamicLibraryBundle.java b/src/java/com/jogamp/common/os/DynamicLibraryBundle.java index 8e138ef..6c00afe 100755 --- a/src/java/com/jogamp/common/os/DynamicLibraryBundle.java +++ b/src/java/com/jogamp/common/os/DynamicLibraryBundle.java @@ -28,10 +28,8 @@ package com.jogamp.common.os; import java.util.*; -import java.security.*; import com.jogamp.common.jvm.JNILibLoaderBase; -import com.jogamp.common.util.MiscUtils; /** * Provides bundling of:
@@ -87,10 +85,10 @@ public class DynamicLibraryBundle implements DynamicLookupHelper { } if(DEBUG) { System.out.println("DynamicLibraryBundle.init Summary: "+info.getClass().getName()); - System.out.println(" toolGetProcAddressFuncNameList: "+MiscUtils.toString(toolGetProcAddressFuncNameList)); - System.out.println(" Tool Lib Names : "+MiscUtils.toString(toolLibNames)); + System.out.println(" toolGetProcAddressFuncNameList: "+toolGetProcAddressFuncNameList); + System.out.println(" Tool Lib Names : "+toolLibNames); System.out.println(" Tool Lib Loaded: "+getToolLibLoadedNumber()+"/"+getToolLibNumber()+", complete "+isToolLibComplete()); - System.out.println(" Glue Lib Names : "+MiscUtils.toString(glueLibNames)); + System.out.println(" Glue Lib Names : "+glueLibNames); System.out.println(" Glue Lib Loaded: "+getGlueLibLoadedNumber()+"/"+getGlueLibNumber()+", complete "+isGlueLibComplete()); System.out.println(" All Complete: "+isLibComplete()); } @@ -209,13 +207,13 @@ public class DynamicLibraryBundle implements DynamicLookupHelper { libNames = new ArrayList(); libNames.add((String)listObj); } else { - throw new RuntimeException("List element "+i+" must be either a List or String: "+MiscUtils.toString(toolLibNames)); + throw new RuntimeException("List element "+i+" must be either a List or String: "+toolLibNames); } if( null != libNames && libNames.size() > 0 ) { lib = loadFirstAvailable(libNames, loader, info.shallLinkGlobal()); if ( null == lib ) { if(DEBUG) { - System.out.println("Unable to load any Tool library of: "+MiscUtils.toString(libNames)); + System.out.println("Unable to load any Tool library of: "+libNames); } } else { nativeLibraries.add(lib); @@ -283,7 +281,7 @@ public class DynamicLibraryBundle implements DynamicLookupHelper { if(0!=addr) { System.err.println("Lookup-Native: <" + funcName + "> 0x" + Long.toHexString(addr) + " in lib " + libName ); } else { - System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** in libs " + MiscUtils.toString(nativeLibraries)); + System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** in libs " + nativeLibraries); } } return addr; diff --git a/src/java/com/jogamp/common/util/MiscUtils.java b/src/java/com/jogamp/common/util/MiscUtils.java deleted file mode 100644 index dd32951..0000000 --- a/src/java/com/jogamp/common/util/MiscUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2010, Sven Gothel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sven Gothel nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jogamp.common.util; - -import java.util.*; - -public class MiscUtils { - - public static StringBuffer append(StringBuffer sb, List list) { - sb.append("["); - if(null!=list&&list.size()>0) { - boolean comma = false; - for(Iterator iter=list.iterator(); iter.hasNext(); ) { - if(comma) { sb.append(", "); } - Object o = iter.next(); - if(o instanceof List) { - sb = append(sb, (List)o); - } else { - sb.append(o); - } - comma = true; - } - } - sb.append("]"); - return sb; - } - - public static String toString(List list) { - return append(new StringBuffer(), list).toString(); - } -} - -- cgit v1.2.3 From 1d9b041200dcc44a353706377bfd6ac999a14d7e Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Thu, 10 Jun 2010 17:20:42 +0200 Subject: small fix in IDE target. Test ran twice in debug mode. --- nbproject/ide-file-targets.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/nbproject/ide-file-targets.xml b/nbproject/ide-file-targets.xml index 343f527..d879376 100644 --- a/nbproject/ide-file-targets.xml +++ b/nbproject/ide-file-targets.xml @@ -50,7 +50,6 @@ - -- cgit v1.2.3 From 9fa4828ffb4ea0c01d349d5847e91c4b6fa6e511 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Thu, 17 Jun 2010 00:41:29 +0200 Subject: pass a ClassLoader to all methods which load classes. (ReflectionUtil) --- .../com/jogamp/common/util/ReflectionUtil.java | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/java/com/jogamp/common/util/ReflectionUtil.java b/src/java/com/jogamp/common/util/ReflectionUtil.java index b9c6ef0..fc4352f 100644 --- a/src/java/com/jogamp/common/util/ReflectionUtil.java +++ b/src/java/com/jogamp/common/util/ReflectionUtil.java @@ -47,9 +47,9 @@ public final class ReflectionUtil { /** * Returns true only if the class could be loaded. */ - public static final boolean isClassAvailable(String clazzName) { + public static final boolean isClassAvailable(String clazzName, ClassLoader cl) { try { - return null != Class.forName(clazzName, false, ReflectionUtil.class.getClassLoader()); + return null != Class.forName(clazzName, false, cl); } catch (ClassNotFoundException e) { return false; } @@ -59,26 +59,26 @@ public final class ReflectionUtil { * Loads and returns the class or null. * @see Class#forName(java.lang.String, boolean, java.lang.ClassLoader) */ - public static final Class getClass(String clazzName, boolean initialize) + public static final Class getClass(String clazzName, boolean initialize, ClassLoader cl) throws JogampRuntimeException { try { - return getClassImpl(clazzName, initialize); + return getClassImpl(clazzName, initialize, cl); } catch (ClassNotFoundException e) { throw new JogampRuntimeException(clazzName + " not available", e); } } - private static Class getClassImpl(String clazzName, boolean initialize) throws ClassNotFoundException { - return Class.forName(clazzName, initialize, ReflectionUtil.class.getClassLoader()); + private static Class getClassImpl(String clazzName, boolean initialize, ClassLoader cl) throws ClassNotFoundException { + return Class.forName(clazzName, initialize, cl); } /** * @throws JogampRuntimeException if the constructor can not be delivered. */ - public static final Constructor getConstructor(String clazzName, Class[] cstrArgTypes) + public static final Constructor getConstructor(String clazzName, ClassLoader cl, Class[] cstrArgTypes) throws JogampRuntimeException { try { - return getConstructor(getClassImpl(clazzName, true), cstrArgTypes); + return getConstructor(getClassImpl(clazzName, true, cl), cstrArgTypes); } catch (ClassNotFoundException ex) { throw new JogampRuntimeException(clazzName + " not available", ex); } @@ -109,9 +109,9 @@ public final class ReflectionUtil { } } - public static final Constructor getConstructor(String clazzName) + public static final Constructor getConstructor(String clazzName, ClassLoader cl) throws JogampRuntimeException { - return getConstructor(clazzName, new Class[0]); + return getConstructor(clazzName, cl, new Class[0]); } /** @@ -147,30 +147,30 @@ public final class ReflectionUtil { return createInstance(clazz, cstrArgTypes, cstrArgs); } - public static final Object createInstance(String clazzName, Class[] cstrArgTypes, Object[] cstrArgs) + public static final Object createInstance(String clazzName, ClassLoader cl, Class[] cstrArgTypes, Object[] cstrArgs) throws JogampRuntimeException, RuntimeException { try { - return createInstance(getClassImpl(clazzName, true), cstrArgTypes, cstrArgs); + return createInstance(getClassImpl(clazzName, true, cl), cstrArgTypes, cstrArgs); } catch (ClassNotFoundException ex) { throw new JogampRuntimeException(clazzName + " not available", ex); } } - public static final Object createInstance(String clazzName, Object[] cstrArgs) + public static final Object createInstance(String clazzName, ClassLoader cl, Object[] cstrArgs) throws JogampRuntimeException, RuntimeException { Class[] cstrArgTypes = new Class[cstrArgs.length]; for(int i=0; i Date: Fri, 18 Jun 2010 23:08:19 +0200 Subject: added 'intptr_t' to the list of PointerBuffer candidates. TODO consider making this configurable. --- src/java/com/sun/gluegen/JavaEmitter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java/com/sun/gluegen/JavaEmitter.java b/src/java/com/sun/gluegen/JavaEmitter.java index 2a51a64..c7156c3 100644 --- a/src/java/com/sun/gluegen/JavaEmitter.java +++ b/src/java/com/sun/gluegen/JavaEmitter.java @@ -1279,8 +1279,8 @@ public class JavaEmitter implements GlueEmitter { if (targetType.isVoid()) { return JavaType.createForVoidPointer(); } else if (targetType.isInt()) { - // size_t is always a PointerBuffer since size is arch dependent - if ("size_t".equals(targetType.getName())) { + // size_t and intptr_t is always a PointerBuffer since size is arch dependent + if ("size_t".equals(targetType.getName()) || "intptr_t".equals(targetType.getName())) { return JavaType.forNIOPointerBufferClass(); } switch ((int) targetType.getSize(curMachDesc)) { -- cgit v1.2.3 From 29072eee5784035d1284d3b9625450681fca25b3 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Fri, 18 Jun 2010 23:24:03 +0200 Subject: added BasicProcAddressEmitterTest testing generation of ProcAddressTable and method RenameJavaMethod property. --- .../sun/gluegen/BasicProcAddressEmitterTest.java | 68 ++++++++++++++++++++++ test/junit/com/sun/gluegen/BuildUtil.java | 14 ++++- test/junit/com/sun/gluegen/dyntest.cfg | 25 ++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 test/junit/com/sun/gluegen/BasicProcAddressEmitterTest.java create mode 100644 test/junit/com/sun/gluegen/dyntest.cfg diff --git a/test/junit/com/sun/gluegen/BasicProcAddressEmitterTest.java b/test/junit/com/sun/gluegen/BasicProcAddressEmitterTest.java new file mode 100644 index 0000000..cdd8bd0 --- /dev/null +++ b/test/junit/com/sun/gluegen/BasicProcAddressEmitterTest.java @@ -0,0 +1,68 @@ +package com.sun.gluegen; + +import com.sun.gluegen.procaddress.ProcAddressEmitter; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; +import org.junit.AfterClass; +import org.junit.Test; +import static java.util.Arrays.*; +import static com.sun.gluegen.BuildUtil.*; +import static org.junit.Assert.*; + +/** + * Basic test using ProcAddressEmitter. + * @author Michael Bien + */ +public class BasicProcAddressEmitterTest { + + @Test + public void generateBindingTest() { + generate("dyntest", "test", ProcAddressEmitter.class.getName()); + } + + /** + * fails if ant script fails (which is a good thing). + * executeTarget throws RuntimeException on failure + */ + @Test + public void compileJavaTest() { + compileJava(); + } + + /* + * fails if ant script fails (which is a good thing) + * executeTarget throws RuntimeException on failure + */ + @Test + public void compileNativesTest() { + compileNatives(); + } + + @Test + public void renameTest() throws Exception { + + Class binding = Class.forName("test.DynBindingTest"); + Class table = Class.forName("test.Table"); + + Field[] fields = table.getDeclaredFields(); + + + Set expected = new HashSet( + asList("arrayTest", "bufferTest", "pbTest", "manyBuffersTest", "mixedTest", "doubleTest")); + + for (Field field : fields) { + System.out.println("address field: "+field); + + String function = field.getName().substring("_addressoff_".length()-1); + assertTrue("unexpected field: '"+function+"'",expected.contains(function)); + } + + } + + @AfterClass + public static void tearDown() { +// cleanGeneratedFiles(); + } + +} diff --git a/test/junit/com/sun/gluegen/BuildUtil.java b/test/junit/com/sun/gluegen/BuildUtil.java index 35dc0c1..0658893 100644 --- a/test/junit/com/sun/gluegen/BuildUtil.java +++ b/test/junit/com/sun/gluegen/BuildUtil.java @@ -109,14 +109,22 @@ public final class BuildUtil { } public static void generate(String bindingName) { + generate(bindingName, JavaEmitter.class.getName()); +// generate(bindingName, DebugEmitter.class.getName()); + } + + public static void generate(String bindingName, String emitter) { + generate(bindingName, bindingName, emitter); + } + public static void generate(String bindingName, String header, String emitter) { - out.println("generate binding: " + bindingName); + out.println("generate binding to '" + bindingName+"' using '"+emitter+"'"); GlueGen.main( "-I"+path, "-O"+testOutput+"/gensrc", - // "-Ecom.sun.gluegen.DebugEmitter", + "-E"+emitter, "-C"+path+"/"+bindingName+".cfg", - path+"/"+bindingName+".h" ); + path+"/"+header+".h" ); out.println("done"); } diff --git a/test/junit/com/sun/gluegen/dyntest.cfg b/test/junit/com/sun/gluegen/dyntest.cfg new file mode 100644 index 0000000..60b8764 --- /dev/null +++ b/test/junit/com/sun/gluegen/dyntest.cfg @@ -0,0 +1,25 @@ +Package test +Style AllStatic +JavaClass DynBindingTest +JavaOutputDir java +NativeOutputDir native + +CustomCCode #include "test.h" + +Import com.jogamp.common.nio.* + + +EmitProcAddressTable true +ProcAddressTableClassName Table +GetProcAddressTableExpr table +ProcAddressNameExpr $UpperCase(arg) + +ForceProcAddressGen __ALL__ + +CustomJavaCode DynBindingTest private final static Table table; +CustomJavaCode DynBindingTest static { +CustomJavaCode DynBindingTest table = new Table(); +CustomJavaCode DynBindingTest //table.reset(); +CustomJavaCode DynBindingTest } + +RenameJavaMethod arrayTest fancyArrayTest \ No newline at end of file -- cgit v1.2.3 From ae37ac16a13aa62cd6e7a6ff0346403c5aa6b3e5 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Sun, 20 Jun 2010 04:34:12 +0200 Subject: 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 --- .../jogamp/gluegen/runtime/ProcAddressTable.java | 177 +++++++++++++++++---- .../gluegen/procaddress/ProcAddressEmitter.java | 76 +++------ 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/**/ 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 "{@link #PROCADDRESS_VAR_PREFIX} + <functionName>" + * 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/**/ 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 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(); @@ -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 "" + PROCADDRESS_VAR_PREFIX + " + "); - w.println(" * <functionName>" 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) { -- cgit v1.2.3