diff options
-rw-r--r-- | make/gl-common.cfg | 19 | ||||
-rw-r--r-- | src/net/java/games/gluegen/ArrayTypes.java | 78 | ||||
-rw-r--r-- | src/net/java/games/gluegen/CMethodBindingEmitter.java | 163 | ||||
-rw-r--r-- | src/net/java/games/gluegen/JavaEmitter.java | 74 | ||||
-rw-r--r-- | src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java | 14 | ||||
-rw-r--r-- | src/net/java/games/gluegen/JavaType.java | 9 | ||||
-rw-r--r-- | src/net/java/games/gluegen/MethodBinding.java | 3 | ||||
-rw-r--r-- | 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 Get<type>ArrayRegion() 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 <type>*, we need to get <type> @@ -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<type>[][], targetType is <type>[], we need to get <type> 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) || |