From 4b93bb531605fa082bdad6452d3e6a51cbb15bed Mon Sep 17 00:00:00 2001 From: Kenneth Russel Date: Mon, 4 Oct 2004 22:55:39 +0000 Subject: Fixed Issue 71: glMultiDrawElements() is missing Added support to GlueGen to handle pointer-to-pointer types for primitive types, like void** and int**. These are exposed as arrays of appropriately-typed direct java.nio Buffers for simplicity. Checks for whether the buffers are direct are performed and null checks for the individual Buffer objects are done as well. Fixed an existing bug in the conversion of outgoing char** arguments in C to String[] in Java where null checks were missing; this showed up as crashes in glShaderSourceARB. Exposed glMultiDrawElements and several other less-common entry points taking void** arguments. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@154 232f8b59-042b-4e1e-8c03-345bb8c30851 --- make/gl-common.cfg | 19 +-- src/net/java/games/gluegen/ArrayTypes.java | 78 ++++++---- .../java/games/gluegen/CMethodBindingEmitter.java | 163 ++++++++++++++------- src/net/java/games/gluegen/JavaEmitter.java | 74 +++++----- .../gluegen/JavaMethodBindingImplEmitter.java | 14 +- src/net/java/games/gluegen/JavaType.java | 9 +- src/net/java/games/gluegen/MethodBinding.java | 3 +- src/net/java/games/gluegen/cgram/types/Type.java | 14 +- 8 files changed, 231 insertions(+), 143 deletions(-) diff --git a/make/gl-common.cfg b/make/gl-common.cfg index feb9025c4..bac2ed325 100644 --- a/make/gl-common.cfg +++ b/make/gl-common.cfg @@ -69,24 +69,7 @@ ManuallyImplement glMapBufferARB Ignore glMapObjectBufferATI Ignore glUnmapObjectBufferATI -# Ignore GL functions that have void** parameters; we cannot yet deal with them -Ignore glMultiDrawElements -Ignore glMultiDrawElements -Ignore glVertexPointervINTEL -Ignore glNormalPointervINTEL -Ignore glColorPointervINTEL -Ignore glTexCoordPointervINTEL -Ignore glMultiDrawElementsEXT -Ignore glReplacementCodePointerSUN -Ignore glMultiModeDrawElementsIBM -Ignore glColorPointerListIBM -Ignore glSecondaryColorPointerListIBM -Ignore glEdgeFlagPointerListIBM -Ignore glFogCoordPointerListIBM -Ignore glIndexPointerListIBM -Ignore glNormalPointerListIBM -Ignore glTexCoordPointerListIBM -Ignore glVertexPointerListIBM +# Ignore some GL functions that have outgoing void** parameters; we cannot yet deal with them Ignore glGetVariantPointervEXT # Some GL functions have multiple void* arguments but require them to diff --git a/src/net/java/games/gluegen/ArrayTypes.java b/src/net/java/games/gluegen/ArrayTypes.java index 86867866a..908a3d765 100644 --- a/src/net/java/games/gluegen/ArrayTypes.java +++ b/src/net/java/games/gluegen/ArrayTypes.java @@ -39,14 +39,14 @@ package net.java.games.gluegen; +import java.nio.*; + /** * Convenience class containing the Class objects corresponding to arrays of * various types (e.g., {@link #booleanArrayClass} is the Class of Java type * "boolean[]"). */ public class ArrayTypes { - /** Class for Java type string[] */ - public static final Class stringArrayClass; /** Class for Java type boolean[] */ public static final Class booleanArrayClass; /** Class for Java type byte[] */ @@ -63,28 +63,47 @@ public class ArrayTypes { public static final Class floatArrayClass; /** Class for Java type double[] */ public static final Class doubleArrayClass; + /** Class for Java type String[] */ + public static final Class stringArrayClass; - /** Class for Java type string[][] */ - public static final Class stringArrayArrayClass; - /** Class for Java type boolean[][] */ - public static final Class booleanArrayArrayClass; - /** Class for Java type byte[][] */ - public static final Class byteArrayArrayClass; - /** Class for Java type char[][] */ - public static final Class charArrayArrayClass; - /** Class for Java type short[][] */ - public static final Class shortArrayArrayClass; - /** Class for Java type int[][] */ - public static final Class intArrayArrayClass; - /** Class for Java type long[][] */ - public static final Class longArrayArrayClass; - /** Class for Java type float[][] */ - public static final Class floatArrayArrayClass; - /** Class for Java type double[][] */ - public static final Class doubleArrayArrayClass; + // Classes for two-dimensional arrays. + // + // GlueGen converts C types like int** into Java arrays of direct + // buffers of the appropriate type (like IntBuffer[]). If the tool + // supported conversions like byte[][] -> char**, it would + // effectively be necessary to copy all of the data from the Java + // heap to the C heap during each call. The reason for this is that + // if we wanted to use GetPrimitiveArrayCritical to lock down the + // storage for each individual array element, we would need to fetch + // each element of the two-dimensional Java array into temporary + // storage before making the first GetPrimitiveArrayCritical call, + // since one can not call GetObjectArrayElement inside a Get / + // ReleasePrimitiveArrayCritical pair. This means that we would need + // two top-level pieces of temporary storage for the two-dimensional + // array as well as two loops to set up the contents, which would be + // too complicated. + // + // The one concession we make is converting String[] -> char**. The + // JVM takes care of the C heap allocation for GetStringUTFChars and + // ReleaseStringUTFChars, and this conversion is important for + // certain OpenGL operations. + + /** Class for Java type Buffer[] */ + public static final Class bufferArrayClass; + /** Class for Java type ByteBuffer[] */ + public static final Class byteBufferArrayClass; + /** Class for Java type ShortBuffer[] */ + public static final Class shortBufferArrayClass; + /** Class for Java type IntBuffer[] */ + public static final Class intBufferArrayClass; + /** Class for Java type LongBuffer[] */ + public static final Class longBufferArrayClass; + /** Class for Java type FloatBuffer[] */ + public static final Class floatBufferArrayClass; + /** Class for Java type DoubleBuffer[] */ + public static final Class doubleBufferArrayClass; static { - stringArrayClass = new String [0].getClass(); booleanArrayClass = new boolean[0].getClass(); byteArrayClass = new byte [0].getClass(); charArrayClass = new char [0].getClass(); @@ -93,15 +112,14 @@ public class ArrayTypes { longArrayClass = new long [0].getClass(); floatArrayClass = new float [0].getClass(); doubleArrayClass = new double [0].getClass(); + stringArrayClass = new String [0].getClass(); - stringArrayArrayClass = new String [0][0].getClass(); - booleanArrayArrayClass = new boolean[0][0].getClass(); - byteArrayArrayClass = new byte [0][0].getClass(); - charArrayArrayClass = new char [0][0].getClass(); - shortArrayArrayClass = new short [0][0].getClass(); - intArrayArrayClass = new int [0][0].getClass(); - longArrayArrayClass = new long [0][0].getClass(); - floatArrayArrayClass = new float [0][0].getClass(); - doubleArrayArrayClass = new double [0][0].getClass(); + bufferArrayClass = new Buffer [0].getClass(); + byteBufferArrayClass = new ByteBuffer [0].getClass(); + shortBufferArrayClass = new ShortBuffer [0].getClass(); + intBufferArrayClass = new IntBuffer [0].getClass(); + longBufferArrayClass = new LongBuffer [0].getClass(); + floatBufferArrayClass = new FloatBuffer [0].getClass(); + doubleBufferArrayClass = new DoubleBuffer[0].getClass(); } } diff --git a/src/net/java/games/gluegen/CMethodBindingEmitter.java b/src/net/java/games/gluegen/CMethodBindingEmitter.java index e0abf86a6..b9cc0091e 100644 --- a/src/net/java/games/gluegen/CMethodBindingEmitter.java +++ b/src/net/java/games/gluegen/CMethodBindingEmitter.java @@ -576,7 +576,7 @@ public class CMethodBindingEmitter extends FunctionEmitter throw new RuntimeException( "Could not copy data for type \"" + cArgType + "\"; copying only supported for types of the form " + - "ptr-to-ptr-to-primitive."); + "ptr-to-ptr-to-type."); } PointerType cArgPtrType = cArgType.asPointer(); if (cArgPtrType == null) { @@ -611,6 +611,13 @@ public class CMethodBindingEmitter extends FunctionEmitter "(jstring) _tmpObj", "(const char*)"+convName+"_copy[_copyIndex]"); } + else if (isNIOBufferClass(subArrayElementJavaType)) + { + emitGetDirectBufferAddress(writer, + "_tmpObj", + cArgElementType.getName(), + convName + "_copy[_copyIndex]"); + } else { // Question: do we always need to copy the sub-arrays, or just @@ -625,7 +632,7 @@ public class CMethodBindingEmitter extends FunctionEmitter cArgElementType.getTargetType().getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !! "(*env)->GetArrayLength(env, _tmpObj)", "Could not allocate buffer during copying of data in argument \\\""+binding.getArgumentName(i)+"\\\""); - // FIXME: copy the data (use GetArrayRegion() calls) + // FIXME: copy the data (use matched Get/ReleasePrimitiveArrayCritical() calls) if (true) throw new RuntimeException( "Cannot yet handle type \"" + cArgType.getName() + "\"; need to add support for copying ptr-to-ptr-to-primitiveType subarrays"); @@ -727,63 +734,58 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(" /* Clean up " + convName + "_copy */"); - // Re-fetch length of array that was copied - String arrayLenName = "_tmpArrayLen"; - writer.print(" "); - writer.print(arrayLenName); - writer.print(" = (*env)->GetArrayLength(env, "); - writer.print(binding.getArgumentName(i)); - writer.println(");"); - - // free each element - PointerType cArgPtrType = cArgType.asPointer(); - if (cArgPtrType == null) { - throw new RuntimeException( - "Could not copy data for type \"" + cArgType + - "\"; currently only pointer types supported."); - } - PointerType cArgElementType = cArgPtrType.getTargetType().asPointer(); + // Only need to perform cleanup for individual array + // elements if they are not direct buffers + if (!isNIOBufferClass(subArrayElementJavaType)) { + // Re-fetch length of array that was copied + String arrayLenName = "_tmpArrayLen"; + writer.print(" "); + writer.print(arrayLenName); + writer.print(" = (*env)->GetArrayLength(env, "); + writer.print(binding.getArgumentName(i)); + writer.println(");"); + + // free each element + PointerType cArgPtrType = cArgType.asPointer(); + if (cArgPtrType == null) { + throw new RuntimeException( + "Could not copy data for type \"" + cArgType + + "\"; currently only pointer types supported."); + } + PointerType cArgElementType = cArgPtrType.getTargetType().asPointer(); - // process each element in the array - writer.println(" for (_copyIndex = 0; _copyIndex < " + arrayLenName +"; ++_copyIndex) {"); - - // get each array element - writer.println(" /* free each element of " +convName +"_copy */"); - String subArrayElementJNITypeString = jniType(subArrayElementJavaType); - writer.print(" _tmpObj = ("); - writer.print(subArrayElementJNITypeString); - writer.print(") (*env)->GetObjectArrayElement(env, "); - writer.print(binding.getArgumentName(i)); - writer.println(", _copyIndex);"); - - if (subArrayElementJNITypeString == "jstring") - { - writer.print(" (*env)->ReleaseStringUTFChars(env, "); - writer.print("(jstring) _tmpObj"); - writer.print(", "); - writer.print(convName+"_copy[_copyIndex]"); - writer.println(");"); - } - else - { - // FIXME: free up stuff here - if (true) throw new RuntimeException( - "Cannot yet handle type \"" + cArgType.getName() + - "\"; need to add support for cleaning up copied ptr-to-ptr-to-primitiveType subarrays"); + // process each element in the array + writer.println(" for (_copyIndex = 0; _copyIndex < " + arrayLenName +"; ++_copyIndex) {"); + + // get each array element + writer.println(" /* free each element of " +convName +"_copy */"); + String subArrayElementJNITypeString = jniType(subArrayElementJavaType); + writer.print(" _tmpObj = ("); + writer.print(subArrayElementJNITypeString); + writer.print(") (*env)->GetObjectArrayElement(env, "); + writer.print(binding.getArgumentName(i)); + writer.println(", _copyIndex);"); + + if (subArrayElementJNITypeString == "jstring") { + writer.print(" (*env)->ReleaseStringUTFChars(env, "); + writer.print("(jstring) _tmpObj"); + writer.print(", "); + writer.print(convName+"_copy[_copyIndex]"); + writer.println(");"); + } else { + if (true) throw new RuntimeException( + "Cannot yet handle type \"" + cArgType.getName() + + "\"; need to add support for cleaning up copied ptr-to-ptr-to-primitiveType subarrays"); + } + writer.println(" }"); } - writer.println(" }"); // free the main array writer.print(" free("); writer.print(convName+"_copy"); writer.println(");"); - - - writer.println(); } // end of cleaning up copied data - - if (EMIT_NULL_CHECKS) { writer.println(" }"); } @@ -1059,10 +1061,12 @@ public class CMethodBindingEmitter extends FunctionEmitter return "j" + javaType.getName(); } else if (javaType == java.lang.String.class) { return "jstring"; + } else if (isNIOBufferClass(javaType)) { + return "jobject"; } else { throw new RuntimeException( "Could not determine JNI type for Java class \"" + - javaType.getName() + "\"; was not String or primitive"); + javaType.getName() + "\"; was not String, primitive or direct buffer"); } } @@ -1112,7 +1116,10 @@ public class CMethodBindingEmitter extends FunctionEmitter String sourceVarName, String receivingVarName) { - writer.print(" "); + writer.print(" if ("); + writer.print(sourceVarName); + writer.println(" != NULL) {"); + writer.print(" "); writer.print(receivingVarName); writer.print(" = (*env)->GetStringUTFChars(env, "); writer.print(sourceVarName); @@ -1124,8 +1131,39 @@ public class CMethodBindingEmitter extends FunctionEmitter writer, receivingVarName, "Failed to get UTF-8 chars for argument \\\""+sourceVarName+"\\\""); } + writer.println(" } else {"); + writer.print(" "); + writer.print(receivingVarName); + writer.println(" = NULL;"); + writer.println(" }"); } + private void emitGetDirectBufferAddress(PrintWriter writer, + String sourceVarName, + String receivingVarTypeString, + String receivingVarName) { + if (EMIT_NULL_CHECKS) { + writer.print(" if ("); + writer.print(sourceVarName); + writer.println(" != NULL) {"); + } + writer.print(" "); + writer.print(receivingVarName); + writer.print(" = ("); + writer.print(receivingVarTypeString); + writer.print(") (*env)->GetDirectBufferAddress(env, "); + writer.print(sourceVarName); + writer.println(");"); + if (EMIT_NULL_CHECKS) { + writer.println(" } else {"); + writer.print(" "); + writer.print(receivingVarName); + writer.println(" = NULL;"); + writer.println(" }"); + } + } + + // Note: if the data in the Type needs to be converted from the Java memory // model to the C memory model prior to calling any C-side functions, then // an extra variable named XXX_copy (where XXX is the value of the @@ -1156,7 +1194,7 @@ public class CMethodBindingEmitter extends FunctionEmitter } else if (elementType == java.lang.String.class) { - ptrTypeString = "jstring *"; + ptrTypeString = "jstring"; } else if (elementType.isArray()) { @@ -1174,6 +1212,11 @@ public class CMethodBindingEmitter extends FunctionEmitter } } + else if (isNIOBufferClass(elementType)) + { + // type is an array of direct buffers of some sort + ptrTypeString = cType.getName(); + } else { // Type is pointer to something we can't/don't handle @@ -1228,6 +1271,12 @@ public class CMethodBindingEmitter extends FunctionEmitter Type cType, String incomingArgumentName, String cVariableName) { + emitGetDirectBufferAddress(writer, + incomingArgumentName, + cType.getName(), + cVariableName); + + /* if (EMIT_NULL_CHECKS) { writer.print(" if ("); writer.print(incomingArgumentName); @@ -1245,6 +1294,7 @@ public class CMethodBindingEmitter extends FunctionEmitter if (EMIT_NULL_CHECKS) { writer.println(" }"); } + */ } protected String pointerConversionArgumentName(int i) { @@ -1280,9 +1330,14 @@ public class CMethodBindingEmitter extends FunctionEmitter if (javaArgType.isArray()) { Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); return (subArrayElementJavaType.isArray() || - subArrayElementJavaType == java.lang.String.class); + subArrayElementJavaType == java.lang.String.class || + isNIOBufferClass(subArrayElementJavaType)); } return false; } + + protected static boolean isNIOBufferClass(Class c) { + return java.nio.Buffer.class.isAssignableFrom(c); + } } diff --git a/src/net/java/games/gluegen/JavaEmitter.java b/src/net/java/games/gluegen/JavaEmitter.java index 46d976b23..33a741364 100644 --- a/src/net/java/games/gluegen/JavaEmitter.java +++ b/src/net/java/games/gluegen/JavaEmitter.java @@ -752,7 +752,7 @@ public class JavaEmitter implements GlueEmitter { } else if (t.isVoid()) { return javaType(Void.TYPE); } else { - if (t.pointerDepth() > 0 || arrayDimension(t) > 0) { + if (t.pointerDepth() > 0 || t.arrayDimension() > 0) { Type targetType; // target type if (t.isPointer()) { // t is *, we need to get @@ -765,7 +765,7 @@ public class JavaEmitter implements GlueEmitter { // Handle Types of form pointer-to-type or array-of-type, like // char* or int[]; these are expanded out into Java primitive // arrays, NIO buffers, or both in expandMethodBinding - if (t.pointerDepth() == 1 || arrayDimension(t) == 1) { + if (t.pointerDepth() == 1 || t.arrayDimension() == 1) { if (targetType.isVoid()) { return JavaType.createForVoidPointer(); } else if (targetType.isInt()) { @@ -808,7 +808,7 @@ public class JavaEmitter implements GlueEmitter { } // Handle Types of form pointer-to-pointer-to-type or // array-of-arrays-of-type, like char** or int[][] - else if (t.pointerDepth() == 2 || arrayDimension(t) == 2) { + else if (t.pointerDepth() == 2 || t.arrayDimension() == 2) { // Get the target type of the target type (targetType was computer earlier // as to be a pointer to the target type, so now we need to get its // target type) @@ -820,28 +820,38 @@ public class JavaEmitter implements GlueEmitter { // t is[][], targetType is [], we need to get bottomType = targetType.asArray().getElementType(); } - if (bottomType.isInt()) { - switch (bottomType.getSize()) - { - case 1: return javaType(ArrayTypes.byteArrayArrayClass); - // FIXME: handle 2,4,8-byte int types here - default: - throw new RuntimeException( - "Could not convert C type \"" + t + "\" to appropriate " + - "Java type; Currently, the only supported depth=2 " + - "pointer/array integer types are \"char**\" and \"char[][]\""); + + if (bottomType.isPrimitive()) { + if (bottomType.isInt()) { + switch (bottomType.getSize()) { + case 1: return javaType(ArrayTypes.byteBufferArrayClass); + case 2: return javaType(ArrayTypes.shortBufferArrayClass); + case 4: return javaType(ArrayTypes.intBufferArrayClass); + case 8: return javaType(ArrayTypes.longBufferArrayClass); + default: throw new RuntimeException("Unknown two-dimensional integer array type of element size " + + bottomType.getSize() + " and name " + bottomType.getName()); + } + } else if (bottomType.isFloat()) { + return javaType(ArrayTypes.floatBufferArrayClass); + } else if (bottomType.isDouble()) { + return javaType(ArrayTypes.doubleBufferArrayClass); + } else { + throw new RuntimeException("Unexpected primitive type " + bottomType.getName() + + " in two-dimensional array"); } - } else if (targetType.isPointer() && (targetType.pointerDepth() == 1)) { + } else if (bottomType.isVoid()) { + return javaType(ArrayTypes.bufferArrayClass); + } else if (targetType.isPointer() && (targetType.pointerDepth() == 1) && + targetType.asPointer().getTargetType().isCompound()) { // Array of pointers; convert as array of StructAccessors return JavaType.createForCArray(targetType); } else { throw new RuntimeException( "Could not convert C type \"" + t + "\" " + "to appropriate Java type; need to add more support for " + - "depth=2 pointer/array types with non-integral target " + - "types [debug info: targetType=\"" + targetType + "\"]"); + "depth=2 pointer/array types [debug info: targetType=\"" + + targetType + "\"]"); } - } else { // can't handle this type of pointer/array argument throw new RuntimeException( @@ -849,7 +859,7 @@ public class JavaEmitter implements GlueEmitter { "appropriate Java type; types with pointer/array depth " + "greater than 2 are not yet supported [debug info: " + "pointerDepth=" + t.pointerDepth() + " arrayDimension=" + - arrayDimension(t) + " targetType=\"" + targetType + "\"]"); + t.arrayDimension() + " targetType=\"" + targetType + "\"]"); } } else { @@ -906,14 +916,6 @@ public class JavaEmitter implements GlueEmitter { return new PrintWriter(new BufferedWriter(new FileWriter(file))); } - private int arrayDimension(Type type) { - ArrayType arrayType = type.asArray(); - if (arrayType == null) { - return 0; - } - return 1 + arrayDimension(arrayType.getElementType()); - } - private boolean isOpaque(Type type) { return (cfg.typeInfo(type, typedefDictionary) != null); } @@ -1187,7 +1189,7 @@ public class JavaEmitter implements GlueEmitter { "Cannot apply ReturnsString configuration directive to \"" + sym + "\". ReturnsString requires native method to have return type \"char *\""); } - binding.setJavaReturnType(JavaType.createForClass(java.lang.String.class)); + binding.setJavaReturnType(javaType(java.lang.String.class)); } else { binding.setJavaReturnType(typeToJavaType(sym.getReturnType(), false)); } @@ -1207,9 +1209,9 @@ public class JavaEmitter implements GlueEmitter { //System.out.println("Forcing conversion of " + binding.getName() + " arg #" + i + " from byte[] to String "); if (mappedType.isCVoidPointerType() || mappedType.isCCharPointerType() || - (mappedType.isArray() && mappedType.getJavaClass() == ArrayTypes.byteArrayArrayClass)) { - // convert mapped type from void* and byte[] to String, or byte[][] to String[] - if (mappedType.getJavaClass() == ArrayTypes.byteArrayArrayClass) { + (mappedType.isArray() && mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass)) { + // convert mapped type from void* and byte[] to String, or ByteBuffer[] to String[] + if (mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass) { mappedType = javaType(ArrayTypes.stringArrayClass); } else { mappedType = javaType(String.class); @@ -1330,22 +1332,22 @@ public class JavaEmitter implements GlueEmitter { variant = mb.createCPrimitivePointerVariant(-1, JavaType.forNIOByteBufferClass()); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCCharPointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.byteArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.byteArrayClass)); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCShortPointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.shortArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.shortArrayClass)); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCInt32PointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.intArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.intArrayClass)); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCInt64PointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.longArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.longArrayClass)); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCFloatPointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.floatArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.floatArrayClass)); if (! result.contains(variant)) result.add(variant); } else if (mb.getJavaReturnType().isCDoublePointerType()) { - variant = mb.createCPrimitivePointerVariant(-1, JavaType.createForClass(ArrayTypes.doubleArrayClass)); + variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.doubleArrayClass)); if (! result.contains(variant)) result.add(variant); } shouldRemoveCurrent = true; diff --git a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java index 78a4a6ced..2701bc2ec 100644 --- a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java +++ b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java @@ -102,10 +102,22 @@ public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter writer.println(" throw new " + getRuntimeExceptionType() + "(\"Length of array \\\"" + binding.getArgumentName(i) + "\\\" was less than the required " + arrayType.getLength() + "\");"); } else { - if (binding.getJavaArgumentType(i).isNIOBuffer()) { + JavaType javaType = binding.getJavaArgumentType(i); + if (javaType.isNIOBuffer()) { writer.println(" if (!BufferFactory.isDirect(" + binding.getArgumentName(i) + "))"); writer.println(" throw new " + getRuntimeExceptionType() + "(\"Argument \\\"" + binding.getArgumentName(i) + "\\\" was not a direct buffer\");"); + } else if (javaType.isNIOBufferArray()) { + String argName = binding.getArgumentName(i); + // Check direct buffer properties of all buffers within + writer.println(" if (" + argName + " != null) {"); + writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); + writer.println(" if (!BufferFactory.isDirect(" + argName + "[_ctr])) {"); + writer.println(" throw new " + getRuntimeExceptionType() + "(\"Element \" + _ctr + \" of argument \\\"" + + binding.getArgumentName(i) + "\\\" was not a direct buffer\");"); + writer.println(" }"); + writer.println(" }"); + writer.println(" }"); } } } diff --git a/src/net/java/games/gluegen/JavaType.java b/src/net/java/games/gluegen/JavaType.java index 6e9d71c2a..2d41a543d 100644 --- a/src/net/java/games/gluegen/JavaType.java +++ b/src/net/java/games/gluegen/JavaType.java @@ -263,9 +263,9 @@ public class JavaType { return "jobjectArray /*elements are String*/"; //return "jobjectArray"; } - else if (elementType == java.nio.ByteBuffer.class) + else if (java.nio.Buffer.class.isAssignableFrom(elementType)) { - return "jobjectArray /*elements are ByteBuffer*/"; + return "jobjectArray /*elements are " + elementType.getName() + "*/"; } else if (elementType.isArray()) { @@ -308,6 +308,11 @@ public class JavaType { return (this == nioByteBufferArrayType); } + public boolean isNIOBufferArray() { + return (isArray() && + (java.nio.Buffer.class.isAssignableFrom(clazz.getComponentType()))); + } + public boolean isString() { return (clazz == java.lang.String.class); } diff --git a/src/net/java/games/gluegen/MethodBinding.java b/src/net/java/games/gluegen/MethodBinding.java index 5a88f00f8..fd2b7b7bc 100644 --- a/src/net/java/games/gluegen/MethodBinding.java +++ b/src/net/java/games/gluegen/MethodBinding.java @@ -185,7 +185,8 @@ public class MethodBinding { Type cArgType = getCArgumentType(i); if (javaArgType.isCompoundTypeWrapper() || javaArgType.isNIOBuffer() || - cArgType.isArray()) { + cArgType.isArray() || + javaArgType.isNIOBufferArray()) { // Needs unwrapping of accessors, checking of array // lengths, or checking of direct buffer property needsBody = true; diff --git a/src/net/java/games/gluegen/cgram/types/Type.java b/src/net/java/games/gluegen/cgram/types/Type.java index 531393aa5..440a762e0 100644 --- a/src/net/java/games/gluegen/cgram/types/Type.java +++ b/src/net/java/games/gluegen/cgram/types/Type.java @@ -225,7 +225,8 @@ public abstract class Type { } /** Helper method for determining how many pointer indirections this - type represents (i.e., "void **" returns 2). */ + type represents (i.e., "void **" returns 2). Returns 0 if this + type is not a pointer type. */ public int pointerDepth() { PointerType pt = asPointer(); if (pt == null) { @@ -234,6 +235,17 @@ public abstract class Type { return 1 + pt.getTargetType().pointerDepth(); } + /** Helper method for determining how many array dimentions this + type represents (i.e., "char[][]" returns 2). Returns 0 if this + type is not an array type. */ + public int arrayDimension() { + ArrayType arrayType = asArray(); + if (arrayType == null) { + return 0; + } + return 1 + arrayType.getElementType().arrayDimension(); + } + /** Helper routine for list equality comparison */ static boolean listsEqual(List a, List b) { return ((a == null && b == null) || -- cgit v1.2.3