From f4e753ff1f39be381307ffdb0fb6bb7a2d323eff Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 17 Jun 2014 08:26:36 +0200 Subject: GlueGen: Add support for 'compound array call-by-value' Completing commit c3054a01990e55ab35756ea23ab7d7c05f24dd37 by allowing passing compound arrays via 'call-by-value. - Creating linear temp heap, copying NIO values into it and passing to C function. Copy-back if not 'const', see below. - Respect 'const' qualifier to skip write-back of temp heap passed to C function - See tag: // FIXME: Compound and Compound-Arrays for code changes and validation of completeness - triggers for compound arrays are: - javaType.isArrayOfCompoundTypeWrappers() - type.isArray() - simplified const query by c-type: FunctionEmitter.isBaseTypeConst(ctype) +++ Tests: Added call-by-value to test1.[ch] binding test! --- .../com/jogamp/gluegen/CMethodBindingEmitter.java | 179 +++++++++++---------- src/java/com/jogamp/gluegen/FunctionEmitter.java | 27 +++- src/java/com/jogamp/gluegen/JavaEmitter.java | 18 +-- .../jogamp/gluegen/JavaMethodBindingEmitter.java | 6 +- src/java/com/jogamp/gluegen/JavaType.java | 3 + src/java/com/jogamp/gluegen/MethodBinding.java | 10 +- .../com/jogamp/gluegen/cgram/types/ArrayType.java | 9 +- .../jogamp/gluegen/cgram/types/FunctionType.java | 14 +- .../gluegen/procaddress/ProcAddressEmitter.java | 3 +- .../gluegen/test/junit/generation/BaseClass.java | 24 +++ .../jogamp/gluegen/test/junit/generation/test1.c | 15 ++ .../jogamp/gluegen/test/junit/generation/test1.h | 3 + 12 files changed, 201 insertions(+), 110 deletions(-) diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java index d214004..0e373d0 100644 --- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java @@ -527,28 +527,6 @@ public class CMethodBindingEmitter extends FunctionEmitter { return (type.getSize(machDesc) == 1); } - /** Checks a type (expected to be pointer) for const-ness */ - protected boolean isConstPtr(Type type) { - if (type.pointerDepth() != 1) { - return false; - } - if (type.asPointer().getTargetType().isConst()) { - return true; - } - return false; - } - - /** Checks a type (expected to be pointer-to-pointer) for const-ness */ - protected boolean isConstPtrPtr(Type type) { - if (type.pointerDepth() != 2) { - return false; - } - if (type.asPointer().getTargetType().asPointer().getTargetType().isConst()) { - return true; - } - return false; - } - /** * Code to init the variables that were declared in * emitBodyVariableDeclarations(), PRIOR TO calling the actual C @@ -617,7 +595,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { // // Note that we properly handle only the case of an array of // compound type wrappers in emitBodyVariablePostCallCleanup below - if (!isConstPtrPtr(cArgType) && + if (!isBaseTypeConst(cArgType) && !javaArgType.isArrayOfCompoundTypeWrappers()) { // FIXME: if the arg type is non-const, the sematics might be that // the function modifies the argument -- we don't yet support @@ -639,24 +617,45 @@ public class CMethodBindingEmitter extends FunctionEmitter { writer.println(");"); // allocate an array to hold each element - if (cArgType.pointerDepth() != 2) { - throw new RuntimeException( - "Could not copy data for type \"" + cArgType + - "\"; copying only supported for types of the form " + - "ptr-to-ptr-to-type."); + final Type cArgElementType, cArgElementType2; + { + int error = 0; + if( cArgType.isPointer() ) { + cArgElementType = cArgType.asPointer().getTargetType(); + if( cArgElementType.isPointer() ) { + // pointer-to-pointer + cArgElementType2 = cArgElementType.asPointer().getTargetType(); + if( cArgElementType2.isPointer() ) { + error = 1; + } + if(cArgType.pointerDepth() != 2) { + error = 2; + } + } else { + cArgElementType2 = null; + if(cArgType.pointerDepth() != 1) { + error = 10; + } + } + } else if( cArgType.isArray() ) { + cArgElementType = cArgType.asArray().getBaseElementType(); + cArgElementType2 = null; + } else { + cArgElementType = null; + cArgElementType2 = null; + error = 100; + } + if( 0 < error ) { + throw new RuntimeException( + "Could not copy data for type \"" + cArgType + + "\"; currently only pointer- and array-types are supported. (error "+error+")"); + } } - 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(); emitMalloc( writer, convName+"_copy", cArgElementType.getName(), - isConstPtrPtr(cArgPtrType), + isBaseTypeConst(cArgType), arrayLenName, "Could not allocate buffer for copying data in argument \\\""+javaArgName+"\\\""); @@ -695,8 +694,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { "_tmpObj", cArgElementType.getName(), convName + "_copy[_copyIndex]", - "_offsetHandle[_copyIndex]", - true); + true, + "_offsetHandle[_copyIndex]", true); } else if (javaArgType.isArrayOfCompoundTypeWrappers()) { // These come down in similar fashion to an array of NIO // Buffers only we do not pass down any integer byte @@ -704,10 +703,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { emitGetDirectBufferAddress(writer, "_tmpObj", cArgElementType.getName(), - convName + "_copy[_copyIndex]", - null, - true); + "("+convName + "_copy + _copyIndex)", + false /* !receivingIsPtrPtr -> linear layout -> use memcpy */, + null, true); } else { + if( null == cArgElementType2 ) { + throw new RuntimeException("XXX: Type "+cArgType+" not properly handled as ptr-to-ptr"); + } // Question: do we always need to copy the sub-arrays, or just // GetPrimitiveArrayCritical on each jobjectarray element and // assign it to the appropriate elements at pointer depth 1? @@ -717,8 +719,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { emitMalloc( writer, convName+"_copy[_copyIndex]", - cArgElementType.getTargetType().getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !! - isConstPtrPtr(cArgPtrType), + cArgElementType2.getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !! + isBaseTypeConst(cArgType), "(*env)->GetArrayLength(env, _tmpObj)", "Could not allocate buffer during copying of data in argument \\\""+javaArgName+"\\\""); // FIXME: copy the data (use matched Get/ReleasePrimitiveArrayCritical() calls) @@ -779,7 +781,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { writer.println(" if ( JNI_FALSE == " + isNIOArgName(i) + " && NULL != " + javaArgName + " ) {"); // Release array - final String modeFlag = isConstPtr(cArgType) || isConstPtrPtr(cArgType) ? "JNI_ABORT" : "0" ; + final String modeFlag = isBaseTypeConst(cArgType) ? "JNI_ABORT" : "0" ; writer.print(" (*env)->ReleasePrimitiveArrayCritical(env, " + javaArgName + ", " + convName + ", "+modeFlag+");"); } else { writer.println(" if ( NULL != " + javaArgName + " ) {"); @@ -790,7 +792,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { // // FIXME: should factor out this whole block of code into a separate // method for clarity and maintenance purposes - if (!isConstPtrPtr(cArgType)) { + if (!isBaseTypeConst(cArgType)) { // FIXME: handle any cleanup from treatment of non-const args, // assuming they were treated differently in // emitBodyVariablePreCallSetup() (see the similar section in that @@ -800,20 +802,12 @@ public class CMethodBindingEmitter extends FunctionEmitter { writer.println(" _tmpArrayLen = (*env)->GetArrayLength(env, " + javaArgName + ");"); writer.println(" for (_copyIndex = 0; _copyIndex < _tmpArrayLen; ++_copyIndex) {"); writer.println(" _tmpObj = (*env)->GetObjectArrayElement(env, " + javaArgName + ", _copyIndex);"); - // We only skip the copy back in limited situations - String copyName = pointerConversionArgumentName(javaArgName) + "_copy"; - writer.println(" if ((" + copyName + "[_copyIndex] == NULL && _tmpObj == NULL) ||"); - writer.println(" (" + copyName + "[_copyIndex] != NULL && _tmpObj != NULL &&"); - writer.println(" (*env)->GetDirectBufferAddress(env, _tmpObj) == " + copyName + "[_copyIndex])) {"); - writer.println(" /* No copy back needed */"); - writer.println(" } else {"); - writer.println(" if (" + copyName + "[_copyIndex] == NULL) {"); - writer.println(" (*env)->SetObjectArrayElement(env, " + javaArgName + ", _copyIndex, NULL);"); - writer.println(" } else {"); - writer.println(" _tmpObj = (*env)->NewDirectByteBuffer(env, " + copyName + "[_copyIndex], sizeof(" + cArgType.getName() + "));"); - writer.println(" (*env)->SetObjectArrayElement(env, " + javaArgName + ", _copyIndex, _tmpObj);"); - writer.println(" }"); - writer.println(" }"); + emitReturnDirectBufferAddress(writer, + "_tmpObj", + cArgType.asArray().getBaseElementType().getName(), + "("+convName + "_copy + _copyIndex)", + false /* receivingIsPtrPtr */, + null); writer.println(" }"); } else { throw new RuntimeException( @@ -921,7 +915,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { javaArgType.isArray() || javaArgType.isArrayOfCompoundTypeWrappers() || ( javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation ) ); - if (isConstPtrPtr(cArgType)) { + if (isBaseTypeConst(cArgType)) { writer.print("const "); } @@ -1065,7 +1059,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (retType.isPointer()) { pointerType = retType.asPointer().getTargetType(); } else { - pointerType = retType.asArray().getElementType(); + pointerType = retType.asArray().getBaseElementType(); } writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx + ", (*env)->NewDirectByteBuffer(env, _res[" + arrayIdx + "], sizeof(" + pointerType.getName() + ")));"); @@ -1319,30 +1313,51 @@ public class CMethodBindingEmitter extends FunctionEmitter { String sourceVarName, String receivingVarTypeString, String receivingVarName, - String byteOffsetVarName, - boolean emitElseClause) { + boolean receivingIsPtrPtr, + String byteOffsetVarName, boolean emitElseClause) { writer.println(" if ( NULL != " + sourceVarName + " ) {"); writer.print(" "); - writer.print(" "); - writer.print(receivingVarName); - writer.print(" = ("); - writer.print(receivingVarTypeString); - - writer.print(") (((char*) (*env)->GetDirectBufferAddress(env, "); - writer.print(sourceVarName); - writer.println(")) + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ");"); + if( receivingIsPtrPtr ) { + writer.print(receivingVarName+" = ("+receivingVarTypeString+") (((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); + writer.println(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ");"); + } else { + // linear layout -> use memcpy + writer.println("memcpy((void *)"+receivingVarName+", (*env)->GetDirectBufferAddress(env, "+sourceVarName+"), sizeof("+receivingVarTypeString+"));"); + } - writer.print(" }"); if (emitElseClause) { - writer.println(" else {"); - writer.print(" "); - writer.print(receivingVarName); - writer.println(" = NULL;"); - writer.println(" }"); + writer.println(" } else {"); + writer.print(" "); + writer.print(" "); + if( receivingIsPtrPtr ) { + writer.print(receivingVarName); + writer.println(" = NULL;"); + } else { + writer.println("memset((void *)"+receivingVarName+", 0, sizeof("+receivingVarTypeString+"));"); + } + } + writer.println(" }"); + writer.println(); + } + + private void emitReturnDirectBufferAddress(PrintWriter writer, + String sourceVarName, + String receivingVarTypeString, + String receivingVarName, + boolean receivingIsPtrPtr, + String byteOffsetVarName) { + writer.print(" "); + writer.print(" "); + if( receivingIsPtrPtr ) { + writer.print("(((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); + writer.println(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ") = "+receivingVarName+";"); + throw new RuntimeException("incomplete implementation"); // FIXME doesn't work, currently unused } else { - writer.println(); + // linear layout -> use memcpy + writer.println("memcpy((*env)->GetDirectBufferAddress(env, "+sourceVarName+"), "+receivingVarName+", sizeof("+receivingVarTypeString+"));"); } + writer.println(); } // Note: if the data in the Type needs to be converted from the Java memory @@ -1412,12 +1427,12 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (cPtrType != null) { cElementTypeName = cPtrType.getTargetType().asPointer().getName(); } - if (isConstPtrPtr(cType)) { + if (isBaseTypeConst(cType)) { writer.print("const "); } writer.print(cElementTypeName+" *"); } else { - if (isConstPtrPtr(cType)) { + if (isBaseTypeConst(cType)) { writer.print("const "); } writer.print(ptrTypeString); @@ -1454,8 +1469,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { incomingArgumentName, cVariableType, cVariableName, - byteOffsetVarName, - false); + true, + byteOffsetVarName, false); } protected String byteOffsetArgName(int i) { diff --git a/src/java/com/jogamp/gluegen/FunctionEmitter.java b/src/java/com/jogamp/gluegen/FunctionEmitter.java index 01a0e12..d193ec2 100644 --- a/src/java/com/jogamp/gluegen/FunctionEmitter.java +++ b/src/java/com/jogamp/gluegen/FunctionEmitter.java @@ -42,14 +42,16 @@ package com.jogamp.gluegen; import java.util.*; import java.io.*; +import com.jogamp.gluegen.cgram.types.Type; + public abstract class FunctionEmitter { public static final EmissionModifier STATIC = new EmissionModifier("static"); - private boolean isInterfaceVal; + private final boolean isInterfaceVal; private final ArrayList modifiers; private CommentEmitter commentEmitter = null; - private PrintWriter defaultOutput; + private final PrintWriter defaultOutput; /** * Constructs the FunctionEmitter with a CommentEmitter that emits nothing. @@ -73,6 +75,25 @@ public abstract class FunctionEmitter { public boolean isInterface() { return isInterfaceVal; } + /** + * Checks the base type of pointer-to-pointer, pointer, array or plain for const-ness. + *

+ * Note: Implementation walks down to the base type and returns it's const-ness. + * Intermediate 'const' qualifier are not considered, e.g. const pointer. + *

+ */ + protected final boolean isBaseTypeConst(Type type) { + if ( 2 == type.pointerDepth() ) { + return type.asPointer().getTargetType().asPointer().getTargetType().isConst(); + } else if ( 1 == type.pointerDepth() ) { + return type.asPointer().getTargetType().isConst(); + } else if( type.isArray() ) { + return type.asArray().getBaseElementType().isConst(); + } else { + return type.isConst(); + } + } + public PrintWriter getDefaultOutput() { return defaultOutput; } public void addModifiers(Iterator mi) { @@ -196,7 +217,7 @@ public abstract class FunctionEmitter { @Override public final String toString() { return emittedForm; } - private String emittedForm; + private final String emittedForm; @Override public int hashCode() { diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index 66e9b24..9a5c2af 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -524,7 +524,7 @@ public class JavaEmitter implements GlueEmitter { cfg.unsupportedExceptionType(), !signatureOnly && needsBody, cfg.tagNativeBinding(), - false, + false, // eraseBufferAndArrayTypes cfg.useNIOOnly(binding.getName()), cfg.useNIODirectOnly(binding.getName()), false, @@ -575,14 +575,14 @@ public class JavaEmitter implements GlueEmitter { // method, don't emit another one if (!cfg.isUnimplemented(binding.getName()) && (binding.needsNIOWrappingOrUnwrapping() || - binding.signatureUsesJavaPrimitiveArrays() || + // binding.signatureUsesJavaPrimitiveArrays() /* excluded below */ || hasPrologueOrEpilogue)) { PrintWriter writer = (cfg.allStatic() ? javaWriter() : javaImplWriter()); // If the binding uses primitive arrays, we are going to emit // the private native entry point for it along with the version // taking only NIO buffers - if (!binding.signatureUsesJavaPrimitiveArrays()) { + if ( !binding.signatureUsesJavaPrimitiveArrays() ) { // (Always) emit the entry point taking only direct buffers JavaMethodBindingEmitter emitter = new JavaMethodBindingEmitter(binding, @@ -591,7 +591,7 @@ public class JavaEmitter implements GlueEmitter { cfg.unsupportedExceptionType(), false, cfg.tagNativeBinding(), - true, + true, // eraseBufferAndArrayTypes cfg.useNIOOnly(binding.getName()), cfg.useNIODirectOnly(binding.getName()), true, @@ -1012,7 +1012,7 @@ public class JavaEmitter implements GlueEmitter { cfg.unsupportedExceptionType(), true, cfg.tagNativeBinding(), - false, + false, // eraseBufferAndArrayTypes true, // FIXME: should unify this with the general emission code true, // FIXME: should unify this with the general emission code false, @@ -1255,7 +1255,7 @@ public class JavaEmitter implements GlueEmitter { targetType = t.asPointer().getTargetType(); } else { // t is [], we need to get - targetType = t.asArray().getElementType(); + targetType = t.asArray().getBaseElementType(); } if (t.pointerDepth() == 2 || t.arrayDimension() == 2) { // Get the target type of the target type (targetType was computer earlier @@ -1297,7 +1297,7 @@ public class JavaEmitter implements GlueEmitter { targetType = t.asPointer().getTargetType(); } else { // t is [], we need to get - targetType = t.asArray().getElementType(); + targetType = t.asArray().getBaseElementType(); } // Handle Types of form pointer-to-type or array-of-type, like @@ -1326,7 +1326,7 @@ public class JavaEmitter implements GlueEmitter { return JavaType.createForCDoublePointer(); } else if (targetType.isCompound()) { if (t.isArray()) { // FIXME: Compound and Compound-Arrays - throw new RuntimeException("Arrays of compound types not handled yet"); + return JavaType.createForCArray(targetType); } // Special cases for known JNI types (in particular for converting jawt.h) if (t.getName() != null && @@ -1361,7 +1361,7 @@ public class JavaEmitter implements GlueEmitter { return JavaType.forNIOPointerBufferClass(); } else { // t is[][], targetType is [], we need to get - bottomType = targetType.asArray().getElementType(); + bottomType = targetType.asArray().getBaseElementType(); LOG.log(WARNING, "typeToJavaType(ptr-ptr): {0}, targetType: {1}, bottomType: {2} -> Unhandled!", new Object[]{t, targetType, bottomType}); } diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java index 5dc5eda..23a8005 100644 --- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java @@ -454,15 +454,13 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { // Check lengths of any incoming arrays if necessary for (int i = 0; i < binding.getNumArguments(); i++) { Type type = binding.getCArgumentType(i); - if (type.isArray()) { + if (type.isArray()) { // FIXME: Compound and Compound-Arrays ArrayType arrayType = type.asArray(); writer.println(" if (" + getArgumentName(i) + ".length < " + arrayType.getLength() + ")"); writer.println(" throw new " + getRuntimeExceptionType() + "(\"Length of array \\\"" + getArgumentName(i) + "\\\" was less than the required " + arrayType.getLength() + "\");"); - // FIXME: What is this ??? Until resolved - throw an exception ! - throw new RuntimeException("????? "+binding+": binding.getCArgumentType("+i+").isArray(): "+type); // FIXME: Compound and Compound-Arrays } else { JavaType javaType = binding.getJavaArgumentType(i); if (javaType.isNIOBuffer()) { @@ -686,7 +684,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { // ByteBuffers back into the wrapper types for (int i = 0; i < binding.getNumArguments(); i++) { JavaType javaArgType = binding.getJavaArgumentType(i); - if (javaArgType.isArrayOfCompoundTypeWrappers()) { + if ( javaArgType.isArrayOfCompoundTypeWrappers() && !isBaseTypeConst(javaArgType.getElementCType()) ) { String argName = binding.getArgumentName(i); writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); writer.println(" if ((" + argName + "[_ctr] == null && " + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr] == null) ||"); diff --git a/src/java/com/jogamp/gluegen/JavaType.java b/src/java/com/jogamp/gluegen/JavaType.java index 5f4b97a..a1cbb01 100644 --- a/src/java/com/jogamp/gluegen/JavaType.java +++ b/src/java/com/jogamp/gluegen/JavaType.java @@ -103,6 +103,9 @@ public class JavaType { public JavaType getElementType() { return new JavaType(elementType); } + public Type getElementCType() { + return elementType; + } /** Creates a JavaType corresponding to the given Java type. This can be used to represent arrays of primitive values or Strings; diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java index 5de604f..d199db1 100644 --- a/src/java/com/jogamp/gluegen/MethodBinding.java +++ b/src/java/com/jogamp/gluegen/MethodBinding.java @@ -53,9 +53,9 @@ import java.util.List; public class MethodBinding { - private FunctionSymbol sym; + private final FunctionSymbol sym; private String renamedMethodName; - private HashSet aliasedNames; + private final HashSet aliasedNames; private JavaType javaReturnType; private List javaArgumentTypes; private boolean computedSignatureProperties; @@ -266,11 +266,11 @@ public class MethodBinding { /** * Returns true if the function needs NIO-related * wrapping/unwrapping or conversion of various arguments. Currently - * this returns the logical OR of signatureUsesNIO() and - * signatureUsesCompoundTypeWrappers(). + * this returns the logical OR of signatureUsesNIO(), + * signatureUsesCompoundTypeWrappers() and signatureUsesArraysOfCompoundTypeWrappers(). */ public boolean needsNIOWrappingOrUnwrapping() { - return (signatureUsesNIO() || signatureUsesCompoundTypeWrappers()); + return (signatureUsesNIO() || signatureUsesCompoundTypeWrappers() || signatureUsesArraysOfCompoundTypeWrappers() ); } /** diff --git a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java index 6cedc9c..678fa10 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java @@ -46,8 +46,8 @@ package com.jogamp.gluegen.cgram.types; should be passed in to the constructor. */ public class ArrayType extends MemoryLayoutType implements Cloneable { - private Type elementType; - private int length; + private final Type elementType; + private final int length; private String computedName; public ArrayType(Type elementType, SizeThunk sizeInBytes, int length, int cvAttributes) { @@ -87,7 +87,7 @@ public class ArrayType extends MemoryLayoutType implements Cloneable { /** Return the bottommost element type if this is a multidimensional array. */ - public Type getBaseElementType() { + public Type getBaseElementType() { ArrayType t = this; while (t.getElementType().isArray()) { t = t.getElementType().asArray(); @@ -112,6 +112,9 @@ public class ArrayType extends MemoryLayoutType implements Cloneable { public String toString(String variableName) { StringBuilder buf = new StringBuilder(); + if(elementType.isConst()) { + buf.append("const "); + } buf.append(elementType.getName()); if (variableName != null) { buf.append(" "); diff --git a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java index bb62eba..70fbc64 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java @@ -45,7 +45,7 @@ import java.util.*; declarations and (via PointerType) function pointers. */ public class FunctionType extends Type implements Cloneable { - private Type returnType; + private final Type returnType; private ArrayList argumentTypes; private ArrayList argumentNames; @@ -136,6 +136,9 @@ public class FunctionType extends Type implements Cloneable { String toString(String functionName, String callingConvention, boolean emitNativeTag, boolean isPointer) { StringBuilder res = new StringBuilder(); + if(isConst()) { + res.append("const "); + } res.append(getReturnType()); res.append(" "); if (isPointer) { @@ -163,11 +166,18 @@ public class FunctionType extends Type implements Cloneable { for (int i = 0; i < n; i++) { Type t = getArgumentType(i); if (t.isFunctionPointer()) { - FunctionType ft = t.asPointer().getTargetType().asFunction(); + Type targetType = t.asPointer().getTargetType(); + if(targetType.isConst()) { + res.append("const "); + } + FunctionType ft = targetType.asFunction(); res.append(ft.toString(getArgumentName(i), callingConvention, false, true)); } else if (t.isArray()) { res.append(t.asArray().toString(getArgumentName(i))); } else { + if(t.isConst()) { + res.append("const "); + } res.append(t); String argumentName = getArgumentName(i); if (argumentName != null) { diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java index afaf7d1..6acaacd 100644 --- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java +++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java @@ -119,8 +119,7 @@ public class ProcAddressEmitter extends JavaEmitter { } protected boolean needsModifiedEmitters(FunctionSymbol sym) { - if (!needsProcAddressWrapper(sym) - || getConfig().isUnimplemented(getAliasedSymName(sym))) { + if (!needsProcAddressWrapper(sym) || getConfig().isUnimplemented(getAliasedSymName(sym))) { return false; } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java index 79af1b7..900d959 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java @@ -1011,5 +1011,29 @@ public class BaseClass extends JunitTracer { System.err.println("ch11.3: sameInstanceByRef "+sameInstanceByRef); Assert.assertFalse(sameInstanceByVal); Assert.assertFalse(sameInstanceByRef); + + final TK_Dimension dim2 = binding.getBoundsValue(1, 2, 3, 4); + final TK_Dimension[] sumands = { dim1, dim2 }; + final TK_Dimension dimSum = binding.addDimensions(sumands); + { + dumpDim("ch11.4: sum-dim ", dimSum); + Assert.assertEquals(11+1, dimSum.getX()); + Assert.assertEquals(22+2, dimSum.getY()); + Assert.assertEquals(33+3, dimSum.getWidth()); + Assert.assertEquals(44+4, dimSum.getHeight()); + } + binding.zeroDimensions(sumands); + { + dumpDim("ch11.5: zero-dim[0] ", sumands[0]); + dumpDim("ch11.5: zero-dim[1] ", sumands[1]); + Assert.assertEquals(0, sumands[0].getX()); + Assert.assertEquals(0, sumands[0].getY()); + Assert.assertEquals(0, sumands[0].getWidth()); + Assert.assertEquals(0, sumands[0].getHeight()); + Assert.assertEquals(0, sumands[1].getX()); + Assert.assertEquals(0, sumands[1].getY()); + Assert.assertEquals(0, sumands[1].getWidth()); + Assert.assertEquals(0, sumands[1].getHeight()); + } } } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c index 9b2fb2d..ca24444 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c @@ -528,3 +528,18 @@ MYAPI Bool MYAPIENTRY isSameInstanceByVal(TK_Dimension s1, TK_Dimension s2) { MYAPI Bool MYAPIENTRY isSameInstanceByRef(const TK_Dimension *s1, const TK_Dimension *s2) { return s1 == s2; } +MYAPI TK_Dimension MYAPIENTRY addDimensions(const TK_Dimension s[2]) { + TK_Dimension r = { s[0].x + s[1].x, s[0].y + s[1].y, + s[0].width + s[1].width, s[0].height + s[1].height }; + return r; +} +MYAPI void MYAPIENTRY zeroDimensions(TK_Dimension s[2]) { + s[0].x = 0; + s[0].y = 0; + s[0].width = 0; + s[0].height = 0; + s[1].x = 0; + s[1].y = 0; + s[1].width = 0; + s[1].height = 0; +} diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h index 779e65d..a487f7a 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h @@ -250,3 +250,6 @@ MYAPI TK_Surface MYAPIENTRY getSurfaceValue(TK_Dimension bounds); MYAPI TK_Dimension MYAPIENTRY getSurfaceBoundsValue(TK_Surface s); MYAPI Bool MYAPIENTRY isSameInstanceByVal(TK_Dimension s1, TK_Dimension s2); MYAPI Bool MYAPIENTRY isSameInstanceByRef(const TK_Dimension *s1, const TK_Dimension *s2); +MYAPI TK_Dimension MYAPIENTRY addDimensions(const TK_Dimension s[2]); +MYAPI void MYAPIENTRY zeroDimensions(TK_Dimension s[2]); + -- cgit v1.2.3