diff options
author | Sven Gothel <[email protected]> | 2014-06-25 10:16:01 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-25 10:16:01 +0200 |
commit | 9ee44e1a289ecbac024662dd5a2ffc42e8add023 (patch) | |
tree | 2946a8bbf78e2fd26d088c35ee24cde3e51648e0 | |
parent | 6cb643671578aa912d16dd17e773d92f4667118b (diff) |
Bug 1025 - GlueGen: Add accessor for compound fields of type array, pointer and string (code generation)
Enhance compound access as delivered by Bug 1022,
to also generate accessors (getter and setter) for
array, pointer and string types.
Allow configuration of array length either via
their internal size (c-header) or config 'ReturnedArrayLength'.
'ReturnedArrayLength' allows specifying a java expression.
Canonical field names of compounds are _now_ specified as
follows for configuration entries:
COMPOUND.FIELD
e.g.
StructA.fieldB
Also allow configuration of pointer fields to be treated as
referenced arrays via 'ReturnedArrayLength'.
Further, allow specifying 'pointer fields' as String values
via 'ReturnsString' configuration.
++++
Implementation details:
- handle above described accessor features
- enhance JavaDoc for generated accessors
- generate native JNI compound and string accessor on demand
- encapsule accessor code generation in their own methods
- enhance exception messages
- enhance type verbosity in debug mode
- verbose debug output via GlueGen.debug()
Tests:
- Features covered by test1.[ch]
and Test1p1JavaEmitter and Test1p2ProcAddressEmitter
- Validated compilation and unit tests for modules:
- joal
- jogl (minor config changes req.)
- jocl (minor config changes req.)
23 files changed, 1886 insertions, 433 deletions
diff --git a/make/build-test.xml b/make/build-test.xml index bb36243..f9092d0 100644 --- a/make/build-test.xml +++ b/make/build-test.xml @@ -601,6 +601,8 @@ chmod 644 ${results}/* \${line.separator} <include name="${build_t.gen.rootrel}/native/Bindingtest1p1Impl_JNI.c"/> <include name="${build_t.gen.rootrel}/native/TK_Engine_JNI.c"/> <include name="${build_t.gen.rootrel}/native/TK_Surface_JNI.c"/> + <include name="${build_t.gen.rootrel}/native/TK_ModelConst_JNI.c"/> + <include name="${build_t.gen.rootrel}/native/TK_ModelMutable_JNI.c"/> </patternset> <c.build c.compiler.src.files="junit.test1p1.c.src.files" @@ -625,6 +627,8 @@ chmod 644 ${results}/* \${line.separator} <include name="${build_t.gen.rootrel}/native/Bindingtest1p2Impl_JNI.c"/> <include name="${build_t.gen.rootrel}/native/TK_Engine_JNI.c"/> <include name="${build_t.gen.rootrel}/native/TK_Surface_JNI.c"/> + <include name="${build_t.gen.rootrel}/native/TK_ModelConst_JNI.c"/> + <include name="${build_t.gen.rootrel}/native/TK_ModelMutable_JNI.c"/> </patternset> <c.build c.compiler.src.files="junit.test1p2.c.src.files" diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat index b59a0cf..9b12e4c 100755 --- a/make/scripts/java-win32.bat +++ b/make/scripts/java-win32.bat @@ -5,11 +5,12 @@ set JAVA_HOME=c:\jdk1.7.0_45_x32 set ANT_PATH=C:\apache-ant-1.8.2
set BLD_DIR=..\%BLD_SUB%
-set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
+REM set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
+set LIB_DIR=..\%BLD_SUB%\test\build\natives
set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%LIB_DIR%;%PATH%
-set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\test\build\gluegen-test.jar;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar
+set CP_ALL=.;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;lib/semantic-versioning/semver.jar;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\gluegen.jar;%BLD_DIR%\gluegen-test-util.jar;%BLD_DIR%\test\build\gluegen-test.jar
echo CP_ALL %CP_ALL%
diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat index cb610e0..904acff 100755 --- a/make/scripts/java-win64.bat +++ b/make/scripts/java-win64.bat @@ -5,11 +5,12 @@ set JAVA_HOME=c:\jdk1.7.0_45_x64 set ANT_PATH=C:\apache-ant-1.8.2
set BLD_DIR=..\%BLD_SUB%
-set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
+REM set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
+set LIB_DIR=..\%BLD_SUB%\test\build\natives
set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%LIB_DIR%;%PATH%
-set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\test\build\gluegen-test.jar;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar
+set CP_ALL=.;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;lib/semantic-versioning/semver.jar;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\gluegen.jar;%BLD_DIR%\gluegen-test-util.jar;%BLD_DIR%\test\build\gluegen-test.jar
echo CP_ALL %CP_ALL%
diff --git a/make/scripts/runtest-x32.bat b/make/scripts/runtest-x32.bat index 5e358a8..2c5e8e2 100755 --- a/make/scripts/runtest-x32.bat +++ b/make/scripts/runtest-x32.bat @@ -1,6 +1,7 @@ -scripts\java-win32.bat com.jogamp.common.GlueGenVersion +REM scripts\java-win32.bat com.jogamp.common.GlueGenVersion REM scripts\java-win32.bat com.jogamp.common.util.TestVersionInfo REM scripts\java-win32.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter +scripts\java-win32.bat com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter REM scripts\java-win32.bat com.jogamp.common.os.TestElfReader01 REM scripts\java-win32.bat com.jogamp.common.util.TestIOUtilURIHandling diff --git a/make/scripts/runtest-x64.bat b/make/scripts/runtest-x64.bat index 6451e5d..6b42c28 100755 --- a/make/scripts/runtest-x64.bat +++ b/make/scripts/runtest-x64.bat @@ -1,6 +1,7 @@ -scripts\java-win64.bat com.jogamp.common.GlueGenVersion +REM scripts\java-win64.bat com.jogamp.common.GlueGenVersion REM scripts\java-win64.bat com.jogamp.common.util.TestVersionInfo REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter +scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter REM scripts\java-win64.bat com.jogamp.common.os.TestElfReader01 REM scripts\java-win64.bat com.jogamp.common.util.TestIOUtil01 diff --git a/src/java/com/jogamp/common/nio/StructAccessor.java b/src/java/com/jogamp/common/nio/StructAccessor.java index d6df083..b1593fe 100644 --- a/src/java/com/jogamp/common/nio/StructAccessor.java +++ b/src/java/com/jogamp/common/nio/StructAccessor.java @@ -117,7 +117,7 @@ public class StructAccessor { public final int getIntAt(int byteOffset, int nativeSizeInBytes) { switch(nativeSizeInBytes) { case 2: - return (int) bb.getShort(byteOffset) & 0x0000FFFF ; + return bb.getShort(byteOffset) & 0x0000FFFF ; case 4: return bb.getInt(byteOffset); case 8: @@ -137,7 +137,7 @@ public class StructAccessor { bb.putInt(byteOffset, v); break; case 8: - bb.putLong(byteOffset, (long)v & 0x00000000FFFFFFFFL ); + bb.putLong(byteOffset, v & 0x00000000FFFFFFFFL ); break; default: throw new InternalError("invalid nativeSizeInBytes "+nativeSizeInBytes); @@ -178,7 +178,7 @@ public class StructAccessor { public final long getLongAt(int byteOffset, int nativeSizeInBytes) { switch(nativeSizeInBytes) { case 4: - return (long) bb.getInt(byteOffset) & 0x00000000FFFFFFFFL; + return bb.getInt(byteOffset) & 0x00000000FFFFFFFFL; case 8: return bb.getLong(byteOffset); default: diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java index 0e373d0..1c9d043 100644 --- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java @@ -909,7 +909,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { writer.print(CMethodBindingEmitter.cThisArgumentName()); } else { writer.print("("); - Type cArgType = binding.getCArgumentType(i); + final Type cArgType = binding.getCArgumentType(i); boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType); boolean needsArrayOffset = !needsDataCopy && ( javaArgType.isArray() || @@ -921,8 +921,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { // if this is a pointer to an unsigned type, add unsigned to the name to avoid compiler warnings if(cArgType.isPointer()) { - Type typeLast = ((PointerType)cArgType).getLastTargetType(); - if(typeLast.isInt() && (((IntType)typeLast).isPrimitiveUnsigned())) { + final Type baseType = cArgType.getBaseElementType(); + if(baseType.isInt() && (((IntType)baseType).isPrimitiveUnsigned())) { writer.print("unsigned "); } } @@ -955,8 +955,18 @@ public class CMethodBindingEmitter extends FunctionEmitter { return binding.getNumArguments(); } - protected void emitBodyCallCFunction(PrintWriter writer) { + private boolean isCStructFunctionPointer = false; + + /** + * If method originates from a struct, see {@link MethodBinding#hasContainingType()}, + * it can either purposed to call a native static function (default) + * or a struct's function pointer. + */ + protected void setIsCStructFunctionPointer(final boolean v) { + isCStructFunctionPointer = v; + } + protected void emitBodyCallCFunction(PrintWriter writer) { // Make the call to the actual C function writer.print(" "); @@ -967,7 +977,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (!cReturnType.isVoid()) { writer.print("_res = "); } - if (binding.hasContainingType()) { + if ( isCStructFunctionPointer && binding.hasContainingType() ) { // Call through function pointer writer.print(CMethodBindingEmitter.cThisArgumentName() + "->"); } @@ -1019,8 +1029,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { // See whether capacity has been specified if (returnValueCapacityExpression != null) { - writer.print( - returnValueCapacityExpression.format(argumentNameArray())); + writer.print( returnValueCapacityExpression.format( argumentNameArray() ) ); } else { if (cReturnType.isPointer() && cReturnType.asPointer().getTargetType().isCompound()) { @@ -1030,7 +1039,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { "for function \"" + binding + "\": " + "Structs to be emitted should have been laid out by this point " + "(type " + cReturnType.asPointer().getTargetType().getName() + " / " + - cReturnType.asPointer().getTargetType() + " was not)" + cReturnType.asPointer().getTargetType() + " was not) for "+binding ); } } @@ -1073,7 +1082,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { throw new RuntimeException( "Could not emit native code for function \"" + binding + - "\": array return values for non-char types not implemented yet"); + "\": array return values for non-char types not implemented yet, for "+binding); // FIXME: This is approximately what will be required here // @@ -1095,8 +1104,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { //writer.print(arrayRes); //writer.println(";"); } else { - System.err.print("Unhandled return type: "+javaReturnType.getDumpString()); - throw new RuntimeException("Unhandled return type"); + System.err.print("Unhandled return type: "+javaReturnType.getDebugString()); + throw new RuntimeException("Unhandled return type: "+javaReturnType.getDebugString()+" for "+binding); } } } @@ -1474,11 +1483,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { } protected String byteOffsetArgName(int i) { - return byteOffsetArgName(binding.getArgumentName(i)); - } - - protected String byteOffsetArgName(String s) { - return s + "_byte_offset"; + return JavaMethodBindingEmitter.byteOffsetArgName(binding.getArgumentName(i)); } protected String isNIOArgName(int i) { diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java index 552b237..771576e 100644 --- a/src/java/com/jogamp/gluegen/JavaConfiguration.java +++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java @@ -492,11 +492,21 @@ public class JavaConfiguration { return returnsString.contains(functionName); } - /** Provides a Java MessageFormat expression indicating the number - of elements in the returned array from the specified function - name. Indicates that the given return value, which must be a - pointer to a CompoundType, is actually an array of the - CompoundType rather than a pointer to a single object. */ + /** + * Returns a MessageFormat string of the Java expression calculating + * the number of elements in the returned array from the specified function + * name. The literal <code>1</code> indicates a single object. + * <p> + * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)}, + * it describes field's array-length or element-count referenced by a pointer. + * </p> + * <p> + * In case of struct fields, this array length will also be used + * for the native C function, i.e. multiplied w/ <code>sizeof(C-Type)</code> + * and passed down to native code, <b>if</b> not overriden by + * either {@link #returnValueCapacity(String)} or {@link #returnValueLength(String)}! + * </p> + */ public String returnedArrayLength(String functionName) { return returnedArrayLengths.get(functionName); } @@ -623,18 +633,29 @@ public class JavaConfiguration { return forcedStructs; } - /** Returns a MessageFormat string of the C expression calculating - the capacity of the java.nio.ByteBuffer being returned from a - native method, or null if no expression has been specified. */ + /** + * Returns a MessageFormat string of the C expression calculating + * the capacity of the java.nio.ByteBuffer being returned from a + * native method, or null if no expression has been specified. + * <p> + * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)}, + * it describes field's array-length or element-count referenced by a pointer. + * </p> + */ public String returnValueCapacity(String functionName) { return returnValueCapacities.get(functionName); } - /** Returns a MessageFormat string of the C expression calculating - the length of the array being returned from a native method, or - null if no expression has been specified. */ - public String returnValueLength(String functionName) { - return returnValueLengths.get(functionName); + /** + * Returns a MessageFormat string of the C expression calculating + * the length of the array being returned from a native method. + * <p> + * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)}, + * it describes field's array-length or element-count referenced by a pointer. + * </p> + */ + public String returnValueLength(String symbol) { + return returnValueLengths.get(symbol); } /** Returns a List of Strings of expressions declaring temporary C @@ -727,8 +748,21 @@ public class JavaConfiguration { } } - /** Returns true if this #define, function, struct, or field within - a struct should be ignored during glue code generation. */ + /** + * Returns the canonical configuration name for a struct field name, + * i.e. 'struct-name'.'field-name' + */ + public static String canonicalStructFieldSymbol(String structName, String fieldName) { + return structName+"."+fieldName; + } + + /** + * Returns true if this #define, function, struct, or field within + * a struct should be ignored during glue code generation of interfaces and implementation. + * <p> + * For struct fields see {@link #canonicalStructFieldSymbol(String, String)}. + * </p> + */ public boolean shouldIgnoreInInterface(String symbol) { if(DEBUG_IGNORES) { dumpIgnoresOnce(); @@ -754,6 +788,13 @@ public class JavaConfiguration { return shouldIgnoreInImpl_Int(symbol); } + /** + * Returns true if this #define, function, struct, or field within + * a struct should be ignored during glue code generation of implementation only. + * <p> + * For struct fields see {@link #canonicalStructFieldSymbol(String, String)}. + * </p> + */ public boolean shouldIgnoreInImpl(String symbol) { return shouldIgnoreInImpl_Int(symbol); } @@ -1195,7 +1236,6 @@ public class JavaConfiguration { } } - @SuppressWarnings("unchecked") protected void readExtendedIntfImplSymbols(StringTokenizer tok, String filename, int lineNo, boolean forInterface, boolean forImplementation, boolean onlyList) { File javaFile; BufferedReader javaReader; @@ -1299,7 +1339,7 @@ public class JavaConfiguration { try { String containingStruct = tok.nextToken(); String name = tok.nextToken(); - ignores.add(Pattern.compile(containingStruct + " " + name)); + ignores.add(Pattern.compile(containingStruct + "\\." + name)); } catch (NoSuchElementException e) { throw new RuntimeException("Error parsing \"IgnoreField\" command at line " + lineNo + " in file \"" + filename + "\"", e); diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index 822c1c9..3125edf 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -659,21 +659,20 @@ public class JavaEmitter implements GlueEmitter { (binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue), !cfg.useNIODirectOnly(binding.getName()), machDescJava); - prepCEmitter(binding, cEmitter); + prepCEmitter(binding.getName(), binding.getJavaReturnType(), cEmitter); allEmitters.add(cEmitter); } } } - protected void prepCEmitter(MethodBinding binding, CMethodBindingEmitter cEmitter) + protected void prepCEmitter(String returnSizeLookupName, JavaType javaReturnType, CMethodBindingEmitter cEmitter) { // See whether we need an expression to help calculate the // length of any return type - JavaType javaReturnType = binding.getJavaReturnType(); if (javaReturnType.isNIOBuffer() || javaReturnType.isCompoundTypeWrapper()) { // See whether capacity has been specified - String capacity = cfg.returnValueCapacity(binding.getName()); + final String capacity = cfg.returnValueCapacity(returnSizeLookupName); if (capacity != null) { cEmitter.setReturnValueCapacityExpression( new MessageFormat(capacity) ); } @@ -688,13 +687,13 @@ public class JavaEmitter implements GlueEmitter { } // See whether length has been specified - String len = cfg.returnValueLength(binding.getName()); + final String len = cfg.returnValueLength(returnSizeLookupName); if (len != null) { cEmitter.setReturnValueLengthExpression( new MessageFormat(len) ); } } - cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(binding.getName())); - cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(binding.getName())); + cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(returnSizeLookupName)); + cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(returnSizeLookupName)); } /** @@ -827,32 +826,35 @@ public class JavaEmitter implements GlueEmitter { } @Override - public void emitStruct(CompoundType structType, String alternateName) throws Exception { - String name = structType.getName(); - if (name == null && alternateName != null) { - name = alternateName; + public void emitStruct(final CompoundType structCType, final String alternateName) throws Exception { + final String structCTypeName; + { + String _name = structCType.getName(); + if (_name == null && alternateName != null) { + _name = alternateName; + } + structCTypeName = _name; } - if (name == null) { - final String structName = structType.getStructName(); + if (structCTypeName == null) { + final String structName = structCType.getStructName(); if ( null != structName && cfg.shouldIgnoreInInterface(structName) ) { return; } - - LOG.log(WARNING, "skipping emission of unnamed struct \"{0}\"", structType); + LOG.log(WARNING, "skipping emission of unnamed struct \"{0}\"", structCType); return; } - if (cfg.shouldIgnoreInInterface(name)) { + if (cfg.shouldIgnoreInInterface(structCTypeName)) { return; } - Type containingCType = canonicalize(new PointerType(SizeThunk.POINTER, structType, 0)); - JavaType containingType = typeToJavaType(containingCType, false, null); - if (!containingType.isCompoundTypeWrapper()) { + final Type containingCType = canonicalize(new PointerType(SizeThunk.POINTER, structCType, 0)); + final JavaType containingJType = typeToJavaType(containingCType, null); + if (!containingJType.isCompoundTypeWrapper()) { return; } - String containingTypeName = containingType.getName(); + final String containingJTypeName = containingJType.getName(); this.requiresStaticInitialization = false; // reset @@ -874,23 +876,36 @@ public class JavaEmitter implements GlueEmitter { // which complies w/ Java types. boolean needsNativeCode = false; + // Native code for calls through function pointers gets emitted // into the abstract base class; Java code which accesses fields // gets emitted into the concrete classes - for (int i = 0; i < structType.getNumFields(); i++) { - if (structType.getField(i).getType().isFunctionPointer()) { - needsNativeCode = true; - break; + for (int i = 0; i < structCType.getNumFields(); i++) { + final Field field = structCType.getField(i); + final Type fieldType = field.getType(); + + final String cfgFieldName0 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, field.getName()); + + if (!cfg.shouldIgnoreInInterface(cfgFieldName0)) { + + final String renamed = cfg.getJavaSymbolRename(cfgFieldName0); + final String fieldName = renamed==null ? field.getName() : renamed; + final String cfgFieldName1 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, fieldName); + + if ( fieldType.isFunctionPointer() || fieldType.isPointer() || requiresGetCStringLength(fieldType, cfgFieldName1) ) { + needsNativeCode = true; + break; + } } } - final String structClassPkg = cfg.packageForStruct(name); + final String structClassPkgName = cfg.packageForStruct(structCTypeName); final PrintWriter javaWriter; final PrintWriter jniWriter; try { javaWriter = openFile(cfg.javaOutputDir() + File.separator + - CodeGenUtils.packageAsPath(structClassPkg) + - File.separator + containingTypeName + ".java", containingTypeName); + CodeGenUtils.packageAsPath(structClassPkgName) + + File.separator + containingJTypeName + ".java", containingJTypeName); if( null == javaWriter ) { // suppress output if openFile deliberately returns null. return; @@ -901,9 +916,9 @@ public class JavaEmitter implements GlueEmitter { if (cfg.nativeOutputUsesJavaHierarchy()) { nRoot += File.separator + CodeGenUtils.packageAsPath(cfg.packageName()); } - jniWriter = openFile(nRoot + File.separator + containingTypeName + "_JNI.c", containingTypeName); + jniWriter = openFile(nRoot + File.separator + containingJTypeName + "_JNI.c", containingJTypeName); CodeGenUtils.emitAutogeneratedWarning(jniWriter, this); - emitCHeader(jniWriter, structClassPkg, containingTypeName); + emitCHeader(jniWriter, structClassPkgName, containingJTypeName); } else { jniWriter = null; } @@ -912,7 +927,7 @@ public class JavaEmitter implements GlueEmitter { } javaWriter.println(); - javaWriter.println("package " + structClassPkg + ";"); + javaWriter.println("package " + structClassPkgName + ";"); javaWriter.println(); javaWriter.println("import java.nio.*;"); javaWriter.println(); @@ -929,13 +944,13 @@ public class JavaEmitter implements GlueEmitter { javaWriter.println(";"); } javaWriter.println(); - List<String> javadoc = cfg.javadocForClass(containingTypeName); + List<String> javadoc = cfg.javadocForClass(containingJTypeName); for (String doc : javadoc) { javaWriter.println(doc); } - javaWriter.print("public class " + containingTypeName + " "); + javaWriter.print("public class " + containingJTypeName + " "); boolean firstIteration = true; - List<String> userSpecifiedInterfaces = cfg.implementedInterfaces(containingTypeName); + List<String> userSpecifiedInterfaces = cfg.implementedInterfaces(containingJTypeName); for (String userInterface : userSpecifiedInterfaces) { if (firstIteration) { javaWriter.print("implements "); @@ -951,85 +966,90 @@ public class JavaEmitter implements GlueEmitter { javaWriter.println(" private static final int mdIdx = MachineDescriptionRuntime.getStatic().ordinal();"); javaWriter.println(); // generate all offset and size arrays - generateOffsetAndSizeArrays(javaWriter, " ", containingTypeName, structType, null, null); /* w/o offset */ + generateOffsetAndSizeArrays(javaWriter, " ", containingJTypeName, structCType, null, null); /* w/o offset */ if( GlueGen.debug() ) { - System.err.printf("SE.__: t %s: %s%n", structType, containingTypeName); + System.err.printf("SE.__: structCType %s%n", structCType.getDebugString()); + System.err.printf("SE.__: contCTypeName %s%n", containingCType.getDebugString()); + System.err.printf("SE.__: contJTypeName %s%n", containingJType.getDebugString()); } - for (int i = 0; i < structType.getNumFields(); i++) { - final Field field = structType.getField(i); + for (int i = 0; i < structCType.getNumFields(); i++) { + final Field field = structCType.getField(i); final Type fieldType = field.getType(); - - if (!cfg.shouldIgnoreInInterface(name + " " + field.getName())) { - final String renamed = cfg.getJavaSymbolRename(field.getName()); + final String cfgFieldName0 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, field.getName()); + if ( !cfg.shouldIgnoreInInterface(cfgFieldName0) ) { + final String renamed = cfg.getJavaSymbolRename(cfgFieldName0); final String fieldName = null==renamed ? field.getName() : renamed; + final String cfgFieldName1 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, fieldName); if (fieldType.isFunctionPointer()) { // no offset/size for function pointer .. if( GlueGen.debug() ) { - System.err.printf("SE.os.%02d: t %s: %s / %s (%s)%n", (i+1), fieldType, field, fieldName, "SKIP FuncPtr"); + System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.getDebugString(), "SKIP FuncPtr"); } } else if (fieldType.isCompound()) { // FIXME: will need to support this at least in order to // handle the union in jawt_Win32DrawingSurfaceInfo (fabricate // a name?) if (fieldType.getName() == null) { - throw new RuntimeException("Anonymous structs as fields not supported yet (field \"" + - field + "\" in type \"" + name + "\")"); + throw new RuntimeException("Anonymous structs as fields not supported yet, field \"" + + cfgFieldName1 + "\", "+fieldType.getDebugString()); } if( GlueGen.debug() ) { - System.err.printf("SE.os.%02d: t %s: %s / %s (%s)%n", (i+1), fieldType, field, fieldName, "compound"); + System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.getDebugString(), "compound"); } generateOffsetAndSizeArrays(javaWriter, " ", fieldName, fieldType, field, null); } else if (fieldType.isArray()) { final Type baseElementType = field.getType().asArray().getBaseElementType(); if( GlueGen.debug() ) { - System.err.printf("SE.os.%02d: t %s: %s / %s - baseType %s (%s)%n", (i+1), fieldType, field, fieldName, baseElementType, "array"); + System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.getDebugString(), "array"); + System.err.printf("SE.os.%02d: baseType %s%n", (i+1), baseElementType.getDebugString()); } generateOffsetAndSizeArrays(javaWriter, " ", fieldName, fieldType, field, null); } else { final JavaType externalJavaType; try { - externalJavaType = typeToJavaType(fieldType, false, machDescJava); + externalJavaType = typeToJavaType(fieldType, machDescJava); } catch (Exception e) { - System.err.println("Error occurred while creating accessor for field \"" + - field.getName() + "\" in type \"" + name + "\""); - throw(e); + throw new RuntimeException("Error occurred while creating accessor for field \"" + + cfgFieldName1 + "\", "+fieldType.getDebugString(), e); } if( GlueGen.debug() ) { - System.err.printf("SE.os.%02d: t %s: %s / %s - javaType %s (%s)%n", (i+1), fieldType, field, fieldName, externalJavaType.getDumpString(), "MISC"); + System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, fieldName, fieldType.getDebugString(), "MISC"); + System.err.printf("SE.os.%02d: javaType %s%n", (i+1), externalJavaType.getDebugString()); } if (externalJavaType.isPrimitive()) { // Primitive type generateOffsetAndSizeArrays(javaWriter, " ", fieldName, null, field, null); /* w/o size */ + generateOffsetAndSizeArrays(javaWriter, "//", fieldName, fieldType, null, null); } else if (externalJavaType.isCPrimitivePointerType()) { - // FIXME: Primitive Pointer type - generateOffsetAndSizeArrays(javaWriter, "// Skipped C-Primitive-Ptr-Type: ", fieldName, fieldType, field, externalJavaType.getDumpString()); + if( requiresGetCStringLength(fieldType, cfgFieldName1) ) { + generateOffsetAndSizeArrays(javaWriter, " ", fieldName, null, field, null); /* w/o size */ + generateOffsetAndSizeArrays(javaWriter, "//", fieldName, fieldType, null, "// "+externalJavaType.getDebugString()); + } else { + generateOffsetAndSizeArrays(javaWriter, "//", fieldName, fieldType, field, "// "+externalJavaType.getDebugString()); + } } else { - // FIXME ??? - generateOffsetAndSizeArrays(javaWriter, "// Skipped Complicated Field: ", fieldName, fieldType, field, externalJavaType.getDumpString()); - LOG.log(WARNING, "Complicated fields (field \"{0}\" of type \"{1}\") not implemented yet: {2}", - new Object[]{field, name, externalJavaType.getDumpString()}); - // throw new RuntimeException("Complicated fields (field \"" + field + "\" of type \"" + t + - // "\") not implemented yet"); + generateOffsetAndSizeArrays(javaWriter, " ", fieldName, null, field, null); /* w/o size */ + generateOffsetAndSizeArrays(javaWriter, "//", fieldName, fieldType, null, "// "+externalJavaType.getDebugString()); } } } else if( GlueGen.debug() ) { - System.err.printf("SE.os.%02d: t %s: %s (IGNORED)%n", (i+1), fieldType, field); + System.err.printf("SE.os.%02d: %s, %s (IGNORED)%n", (i+1), field, fieldType.getDebugString()); } } javaWriter.println(); javaWriter.println(" public static int size() {"); - javaWriter.println(" return "+containingTypeName+"_size[mdIdx];"); + javaWriter.println(" return "+containingJTypeName+"_size[mdIdx];"); javaWriter.println(" }"); javaWriter.println(); - javaWriter.println(" public static " + containingTypeName + " create() {"); + javaWriter.println(" public static " + containingJTypeName + " create() {"); javaWriter.println(" return create(Buffers.newDirectByteBuffer(size()));"); javaWriter.println(" }"); javaWriter.println(); - javaWriter.println(" public static " + containingTypeName + " create(java.nio.ByteBuffer buf) {"); - javaWriter.println(" return new " + containingTypeName + "(buf);"); + javaWriter.println(" public static " + containingJTypeName + " create(java.nio.ByteBuffer buf) {"); + javaWriter.println(" return new " + containingJTypeName + "(buf);"); javaWriter.println(" }"); javaWriter.println(); - javaWriter.println(" " + containingTypeName + "(java.nio.ByteBuffer buf) {"); + javaWriter.println(" " + containingJTypeName + "(java.nio.ByteBuffer buf) {"); javaWriter.println(" accessor = new StructAccessor(buf);"); javaWriter.println(" }"); javaWriter.println(); @@ -1037,168 +1057,52 @@ public class JavaEmitter implements GlueEmitter { javaWriter.println(" return accessor.getBuffer();"); javaWriter.println(" }"); - for (int i = 0; i < structType.getNumFields(); i++) { - final Field field = structType.getField(i); + Set<MethodBinding> methodBindingSet = new HashSet<MethodBinding>(); + + for (int i = 0; i < structCType.getNumFields(); i++) { + final Field field = structCType.getField(i); final Type fieldType = field.getType(); - if (!cfg.shouldIgnoreInInterface(name + " " + field.getName())) { - final String renamed = cfg.getJavaSymbolRename(field.getName()); + final String cfgFieldName0 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, field.getName()); + if (!cfg.shouldIgnoreInInterface(cfgFieldName0)) { + final String renamed = cfg.getJavaSymbolRename(cfgFieldName0); final String fieldName = renamed==null ? field.getName() : renamed; + final String cfgFieldName1 = JavaConfiguration.canonicalStructFieldSymbol(structCTypeName, fieldName); + if( GlueGen.debug() ) { + System.err.printf("SE.ac.%02d: %s / %s, %s%n", (i+1), field, cfgFieldName1, fieldType.getDebugString()); + } if (fieldType.isFunctionPointer()) { - if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: t %s: %s / %s (%s)%n", (i+1), fieldType, field, fieldName, "funcPtr"); - } - try { - // Emit method call and associated native code - final FunctionType funcType = fieldType.asPointer().getTargetType().asFunction(); - final FunctionSymbol funcSym = new FunctionSymbol(fieldName, funcType); - final MethodBinding binding = bindFunction(funcSym, containingType, containingCType, machDescJava); - binding.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis - javaWriter.println(); - - // Emit public Java entry point for calling this function pointer - JavaMethodBindingEmitter emitter = - new JavaMethodBindingEmitter(binding, - javaWriter, - cfg.runtimeExceptionType(), - cfg.unsupportedExceptionType(), - true, - cfg.tagNativeBinding(), - false, // eraseBufferAndArrayTypes - true, // FIXME: should unify this with the general emission code - true, // FIXME: should unify this with the general emission code - false, - false, // FIXME: should unify this with the general emission code - false, // FIXME: should unify this with the general emission code - false, // FIXME: should unify this with the general emission code - false, - cfg); - emitter.addModifier(JavaMethodBindingEmitter.PUBLIC); - emitter.emit(); - - // Emit private native Java entry point for calling this function pointer - emitter = - new JavaMethodBindingEmitter(binding, - javaWriter, - cfg.runtimeExceptionType(), - cfg.unsupportedExceptionType(), - false, - cfg.tagNativeBinding(), - true, - true, // FIXME: should unify this with the general emission code - true, // FIXME: should unify this with the general emission code - true, - true, // FIXME: should unify this with the general emission code - false, // FIXME: should unify this with the general emission code - false, // FIXME: should unify this with the general emission code - false, - cfg); - emitter.addModifier(JavaMethodBindingEmitter.PRIVATE); - emitter.addModifier(JavaMethodBindingEmitter.NATIVE); - emitter.emit(); - - // Emit (private) C entry point for calling this function pointer - CMethodBindingEmitter cEmitter = - new CMethodBindingEmitter(binding, - jniWriter, - structClassPkg, - containingTypeName, - true, // FIXME: this is optional at this point - false, - true, - false, // FIXME: should unify this with the general emission code - machDescJava); - prepCEmitter(binding, cEmitter); - cEmitter.emit(); - } catch (Exception e) { - System.err.println("While processing field " + field + " of type " + name + ":"); - throw(e); - } + generateFunctionPointerCode(methodBindingSet, javaWriter, jniWriter, structCTypeName, structClassPkgName, + containingCType, containingJType, i, + new FunctionSymbol(fieldName, fieldType.asPointer().getTargetType().asFunction()), cfgFieldName1); } else if (fieldType.isCompound()) { // FIXME: will need to support this at least in order to // handle the union in jawt_Win32DrawingSurfaceInfo (fabricate a name?) if (fieldType.getName() == null) { throw new RuntimeException("Anonymous structs as fields not supported yet (field \"" + - field + "\" in type \"" + name + "\")"); + field + "\" in type \"" + structCTypeName + "\")"); } - if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: t %s: %s / %s (%s)%n", (i+1), fieldType, field, fieldName, "compound"); - } - javaWriter.println(); - generateGetterSignature(javaWriter, false, fieldType.getName(), capitalizeString(fieldName)); + generateGetterSignature(javaWriter, fieldType, false, fieldType.getName(), capitalizeString(fieldName), null, null); javaWriter.println(" {"); javaWriter.println(" return " + fieldType.getName() + ".create( accessor.slice( " + fieldName+"_offset[mdIdx], "+fieldName+"_size[mdIdx] ) );"); javaWriter.println(" }"); - } else if (fieldType.isArray()) { - final Type baseElementType = field.getType().asArray().getBaseElementType(); - final JavaType paramType = typeToJavaType(baseElementType, false, machDescJava); - - final String paramTypeName = paramType.getName(); - final String capitalized = capitalizeString(fieldName); - if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: t %s: %s / %s - baseType %s, paramType %s (%s)%n", (i+1), fieldType, field, fieldName, baseElementType, paramType.getDumpString(), "array"); - } - - // Setter - javaWriter.println(); - generateSetterSignature(javaWriter, false, containingTypeName, capitalized, paramTypeName+"[]"); - javaWriter.println(" {"); - if(baseElementType.isPrimitive()) { - javaWriter.print (" accessor.set" + capitalizeString(paramTypeName) + "sAt(" + fieldName+"_offset[mdIdx], val);"); - javaWriter.println(" return this;"); - } else { - javaWriter.println(" final int elemSize = "+paramTypeName+".size();"); - javaWriter.println(" final ByteBuffer destB = getBuffer();"); - javaWriter.println(" int offset = "+fieldName+"_offset[mdIdx];"); - javaWriter.println(" final int total = "+fieldType.asArray().getLength()+" * elemSize;"); - javaWriter.println(" if( total > "+fieldName+"_size[mdIdx] ) { throw new IndexOutOfBoundsException(\"total \"+total+\" > size \"+"+fieldName+"_size[mdIdx]+\", elemSize \"+elemSize+\" * "+fieldType.asArray().getLength()+"\"); };"); - javaWriter.println(" final int limes = offset + total;"); - javaWriter.println(" if( limes >= destB.limit() ) { throw new IndexOutOfBoundsException(\"limes \"+limes+\" >= buffer.limit \"+destB.limit()+\", elemOff \"+offset+\", elemSize \"+elemSize+\" * "+fieldType.asArray().getLength()+"\"); };"); - javaWriter.println(" for(int e=0; e<"+fieldType.asArray().getLength()+"; e++) {"); - javaWriter.println(" final "+paramTypeName+" source = val[e];"); - javaWriter.println(" final ByteBuffer sourceB = source.getBuffer();"); - javaWriter.println(" for(int f=0; f<elemSize; f++) {"); - javaWriter.println(" if( offset >= limes ) { throw new IndexOutOfBoundsException(\"elem-byte[\"+e+\"][\"+f+\"]: offset \"+offset+\" >= limes \"+limes+\", elemSize \"+elemSize+\" * "+fieldType.asArray().getLength()+"\"); };"); - javaWriter.println(" destB.put(offset++, sourceB.get(f));"); - javaWriter.println(" }"); - javaWriter.println(" }"); - javaWriter.println(" return this;"); - } - javaWriter.println(" }"); - javaWriter.println(); - // Getter - generateGetterSignature(javaWriter, false, paramTypeName+"[]", capitalized); - javaWriter.println(" {"); - if(baseElementType.isPrimitive()) { - javaWriter.print (" return accessor.get" + capitalizeString(paramTypeName) + "sAt(" + fieldName+"_offset[mdIdx], new " +paramTypeName+"["+fieldType.asArray().getLength()+"]);"); - } else { - javaWriter.println(" final "+paramTypeName+"[] res = new "+paramTypeName+"["+fieldType.asArray().getLength()+"];"); - javaWriter.println(" int offset = "+fieldName+"_offset[mdIdx];"); - javaWriter.println(" final int elemSize = "+paramTypeName+".size();"); - javaWriter.println(" for(int e=0; e<"+fieldType.asArray().getLength()+"; e++) {"); - javaWriter.println(" res[e] = "+paramTypeName+".create(accessor.slice(offset, elemSize));"); - javaWriter.println(" offset += elemSize;"); - javaWriter.println(" }"); - javaWriter.println(" return res;"); - } - javaWriter.println(" }"); + } else if ( fieldType.isArray() || fieldType.isPointer() ) { + generateArrayGetterSetterCode(methodBindingSet, javaWriter, jniWriter, structCTypeName, structClassPkgName, + containingCType, containingJType, + i, field, fieldName, cfgFieldName1); } else { final JavaType javaType; - try { - javaType = typeToJavaType(fieldType, false, machDescJava); + javaType = typeToJavaType(fieldType, machDescJava); } catch (Exception e) { System.err.println("Error occurred while creating accessor for field \"" + - field.getName() + "\" in type \"" + name + "\""); + field.getName() + "\", "+fieldType.getDebugString()); throw(e); } - if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: t %s: %s / %s - javaType %s (%s)%n", (i+1), fieldType, field, fieldName, javaType.getDumpString(), "MISC"); - } if (javaType.isPrimitive()) { // Primitive type final boolean fieldTypeNativeSizeFixed = fieldType.getSize().hasFixedNativeSize(); @@ -1213,26 +1117,27 @@ public class JavaEmitter implements GlueEmitter { final String sizeDenominator = fieldType.isPointer() ? "pointer" : javaTypeName ; if(GlueGen.debug()) { - System.err.println("Java.StructEmitter.Primitive: "+field.getName()+", "+fieldType.getName(true)+", "+javaTypeName+", "+ - ", fixedSize "+fieldTypeNativeSizeFixed+", opaque "+isOpaque(fieldType)+", isPointer "+fieldType.isPointer()+", isCompound "+fieldType.isCompound()+ - ", sizeDenominator "+sizeDenominator); + System.err.println("Java.StructEmitter.Primitive: "+field.getName()+", "+fieldType.getDebugString()+", "+javaTypeName+", "+ + ", fixedSize "+fieldTypeNativeSizeFixed+", opaque "+isOpaque(fieldType)+", sizeDenominator "+sizeDenominator); } - javaWriter.println(); - // Setter - generateSetterSignature(javaWriter, false, containingTypeName, capFieldName, javaTypeName); - javaWriter.println(" {"); - if( fieldTypeNativeSizeFixed ) { - javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val);"); - } else { - javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val, MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); + if( !fieldType.isConst() ) { + // Setter + javaWriter.println(); + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capFieldName, null, javaTypeName, null, null); + javaWriter.println(" {"); + if( fieldTypeNativeSizeFixed ) { + javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val);"); + } else { + javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val, MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); + } + javaWriter.println(" return this;"); + javaWriter.println(" }"); } - javaWriter.println(" return this;"); - javaWriter.println(" }"); - javaWriter.println(); // Getter - generateGetterSignature(javaWriter, false, javaTypeName, capFieldName); + javaWriter.println(); + generateGetterSignature(javaWriter, fieldType, false, javaTypeName, capFieldName, null, null); javaWriter.println(" {"); javaWriter.print (" return "); if( fieldTypeNativeSizeFixed ) { @@ -1241,30 +1146,31 @@ public class JavaEmitter implements GlueEmitter { javaWriter.println("accessor.get" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); } javaWriter.println(" }"); - } else if (javaType.isCPrimitivePointerType()) { - // FIXME: Primitive Pointer type + } else { javaWriter.println(); - javaWriter.println(" /** "+fieldName +": "+javaType.getDumpString()+" */"); + javaWriter.println(" /** UNKNOWN: "+cfgFieldName1 +": "+fieldType.getDebugString()+", "+javaType.getDebugString()+" */"); } } } } - emitCustomJavaCode(javaWriter, containingTypeName); + emitCustomJavaCode(javaWriter, containingJTypeName); if (needsNativeCode) { javaWriter.println(); - emitJavaInitCode(javaWriter, containingTypeName); + emitJavaInitCode(javaWriter, containingJTypeName); javaWriter.println(); } javaWriter.println("}"); javaWriter.flush(); javaWriter.close(); if (needsNativeCode) { - emitCInitCode(jniWriter, structClassPkg, containingTypeName); + emitCInitCode(jniWriter, structClassPkgName, containingJTypeName); jniWriter.flush(); jniWriter.close(); } if( GlueGen.debug() ) { - System.err.printf("SE.XX: t %s: %s%n", structType, containingTypeName); + System.err.printf("SE.XX: structCType %s%n", structCType.getDebugString()); + System.err.printf("SE.XX: contCTypeName %s%n", containingCType.getDebugString()); + System.err.printf("SE.XX: contJTypeName %s%n", containingJType.getDebugString()); } } @Override @@ -1298,12 +1204,39 @@ public class JavaEmitter implements GlueEmitter { // Internals only below this point // - private void generateGetterSignature(PrintWriter writer, boolean abstractMethod, String returnTypeName, String capitalizedFieldName) { - writer.print(" public " + (abstractMethod ? "abstract " : "") + returnTypeName + " get" + capitalizedFieldName + "()"); + private void generateGetterSignature(final PrintWriter writer, final Type origFieldType, final boolean abstractMethod, + final String returnTypeName, final String capitalizedFieldName, + final String customArgs, final String arrayLengthExpr) { + writer.print(" /** Getter for native field: "+origFieldType.getDebugString()); + if( null != arrayLengthExpr ) { + writer.print(", with array length of <code>"+arrayLengthExpr+"</code>"); + } + writer.println(" */"); + writer.print(" public " + (abstractMethod ? "abstract " : "") + returnTypeName + " get" + capitalizedFieldName + "("); + if( null != customArgs ) { + writer.print(customArgs); + } + writer.print(")"); } - private void generateSetterSignature(PrintWriter writer, boolean abstractMethod, String returnTypeName, String capitalizedFieldName, String paramTypeName) { - writer.print(" public " + (abstractMethod ? "abstract " : "") + returnTypeName + " set" + capitalizedFieldName + "(" + paramTypeName + " val)"); + private void generateSetterSignature(final PrintWriter writer, final Type origFieldType, final boolean abstractMethod, + final String returnTypeName, final String capitalizedFieldName, + final String customArgsPre, final String paramTypeName, final String customArgsPost, + final String arrayLengthExpr) { + writer.print(" /** Setter for native field: "+origFieldType.getDebugString()); + if( null != arrayLengthExpr ) { + writer.print(", with array length of <code>"+arrayLengthExpr+"</code>"); + } + writer.println(" */"); + writer.print(" public " + (abstractMethod ? "abstract " : "") + returnTypeName + " set" + capitalizedFieldName + "("); + if( null != customArgsPre ) { + writer.print(customArgsPre+", "); + } + writer.print(paramTypeName + " val"); + if( null != customArgsPost ) { + writer.print(", "+customArgsPost); + } + writer.print(")"); } private void generateOffsetAndSizeArrays(PrintWriter writer, String prefix, String fieldName, Type fieldType, Field field, String postfix) { @@ -1336,31 +1269,682 @@ public class JavaEmitter implements GlueEmitter { } } - private JavaType typeToJavaType(Type cType, boolean outgoingArgument, MachineDescription curMachDesc) { + private void generateFunctionPointerCode(final Set<MethodBinding> methodBindingSet, + final PrintWriter javaWriter, final PrintWriter jniWriter, + final String structCTypeName, final String structClassPkgName, + final Type containingCType, final JavaType containingJType, + final int i, final FunctionSymbol funcSym, final String returnSizeLookupName) { + // Emit method call and associated native code + final MethodBinding mb = bindFunction(funcSym, containingJType, containingCType, machDescJava); + mb.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis + + // JavaTypes representing C pointers in the initial + // MethodBinding have not been lowered yet to concrete types + final List<MethodBinding> bindings = expandMethodBinding(mb); + + final boolean useNIOOnly = true; + final boolean useNIODirectOnly = true; + + for (final MethodBinding binding : bindings) { + if(!methodBindingSet.add(binding)) { + // skip .. already exisiting binding .. + continue; + } + javaWriter.println(); + // Emit public Java entry point for calling this function pointer + JavaMethodBindingEmitter emitter = + new JavaMethodBindingEmitter(binding, + javaWriter, + cfg.runtimeExceptionType(), + cfg.unsupportedExceptionType(), + true, + cfg.tagNativeBinding(), + false, // eraseBufferAndArrayTypes + useNIOOnly, + useNIODirectOnly, + false, + false, // FIXME: should unify this with the general emission code + false, // forIndirectBufferAndArrayImplementation + false, // FIXME: should unify this with the general emission code + false, + cfg); + emitter.addModifier(JavaMethodBindingEmitter.PUBLIC); + emitter.emit(); + + // Emit private native Java entry point for calling this function pointer + emitter = + new JavaMethodBindingEmitter(binding, + javaWriter, + cfg.runtimeExceptionType(), + cfg.unsupportedExceptionType(), + false, + cfg.tagNativeBinding(), + true, // eraseBufferAndArrayTypes + useNIOOnly, + useNIODirectOnly, + true, + true, // FIXME: should unify this with the general emission code + false, // forIndirectBufferAndArrayImplementation + false, // FIXME: should unify this with the general emission code + false, + cfg); + emitter.addModifier(JavaMethodBindingEmitter.PRIVATE); + emitter.addModifier(JavaMethodBindingEmitter.NATIVE); + emitter.emit(); + + // Emit (private) C entry point for calling this function pointer + CMethodBindingEmitter cEmitter = + new CMethodBindingEmitter(binding, + jniWriter, + structClassPkgName, + containingJType.getName(), + true, // FIXME: this is optional at this point + false, + true, + false, // forIndirectBufferAndArrayImplementation + machDescJava); + cEmitter.setIsCStructFunctionPointer(true); + prepCEmitter(returnSizeLookupName, binding.getJavaReturnType(), cEmitter); + cEmitter.emit(); + } + } + + private void generateArrayPointerCode(final Set<MethodBinding> methodBindingSet, + final PrintWriter javaWriter, final PrintWriter jniWriter, + final String structCTypeName, final String structClassPkgName, + final Type containingCType, final JavaType containingJType, + final int i, final FunctionSymbol funcSym, + final String returnSizeLookupName, final String docArrayLenExpr, final String nativeArrayLenExpr) { + // Emit method call and associated native code + final MethodBinding mb = bindFunction(funcSym, containingJType, containingCType, machDescJava); + mb.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis + + // JavaTypes representing C pointers in the initial + // MethodBinding have not been lowered yet to concrete types + final List<MethodBinding> bindings = expandMethodBinding(mb); + + final boolean useNIOOnly = true; + final boolean useNIODirectOnly = true; + + for (final MethodBinding binding : bindings) { + if(!methodBindingSet.add(binding)) { + // skip .. already exisiting binding .. + continue; + } + JavaMethodBindingEmitter emitter; + + // Emit private native Java entry point for calling this function pointer + emitter = + new JavaMethodBindingEmitter(binding, + javaWriter, + cfg.runtimeExceptionType(), + cfg.unsupportedExceptionType(), + false, + cfg.tagNativeBinding(), + true, // eraseBufferAndArrayTypes + useNIOOnly, + useNIODirectOnly, + true, + true, // FIXME: should unify this with the general emission code + false, // forIndirectBufferAndArrayImplementation + false, // FIXME: should unify this with the general emission code + false, + cfg); + if( null != docArrayLenExpr ) { + emitter.setReturnedArrayLengthExpression(docArrayLenExpr, true); + } + emitter.addModifier(JavaMethodBindingEmitter.PRIVATE); + emitter.addModifier(JavaMethodBindingEmitter.NATIVE); + emitter.emit(); + + // Emit (private) C entry point for calling this function pointer + CMethodBindingEmitter cEmitter = + new CMethodBindingEmitter(binding, + jniWriter, + structClassPkgName, + containingJType.getName(), + true, // FIXME: this is optional at this point + false, + true, + false, // forIndirectBufferAndArrayImplementation + machDescJava); + cEmitter.setIsCStructFunctionPointer(false); + final String lenExprSet; + if( null != nativeArrayLenExpr ) { + JavaType javaReturnType = binding.getJavaReturnType(); + if (javaReturnType.isNIOBuffer() || + javaReturnType.isCompoundTypeWrapper()) { + final Type retType = funcSym.getReturnType(); + final Type baseType = retType.getBaseElementType(); + lenExprSet = nativeArrayLenExpr+" * sizeof("+baseType.getName()+")"; + cEmitter.setReturnValueCapacityExpression( new MessageFormat(lenExprSet) ); + } else if (javaReturnType.isArray() || + javaReturnType.isArrayOfCompoundTypeWrappers()) { + lenExprSet = nativeArrayLenExpr; + cEmitter.setReturnValueLengthExpression( new MessageFormat(lenExprSet) ); + } else { + lenExprSet = null; + } + } else { + lenExprSet = null; + } + prepCEmitter(returnSizeLookupName, binding.getJavaReturnType(), cEmitter); + cEmitter.emit(); + } + } + + private String getArrayArrayLengthExpr(final ArrayType type, final String returnSizeLookupName, final boolean hasFixedTypeLen[], final int[][] lengthRes) { + final int[] length = new int[type.arrayDimension()]; + lengthRes[0] = length; + final StringBuilder lengthExpr = new StringBuilder(); + hasFixedTypeLen[0] = true; + ArrayType typeIter = type; + for(int i=0; i<length.length; i++) { + if( null!=typeIter && typeIter.hasLength() ) { + length[i] = typeIter.getLength(); + if( 0 < i ) { + lengthExpr.append("*"); + } + lengthExpr.append(length[i]); + } else { + length[i] = -1; + hasFixedTypeLen[0] = false; + } + if( null != typeIter ) { + typeIter = typeIter.getElementType().asArray(); + } + } + final String cfgVal = cfg.returnedArrayLength(returnSizeLookupName); + if( null != cfgVal ) { + if( hasFixedTypeLen[0] ) { + System.err.println("WARNING: struct array field '"+returnSizeLookupName+"' of '"+type+"' length '"+Arrays.toString(length)+"' overwritten by cfg-expression: "+cfgVal); + } + return cfgVal; + } + if( hasFixedTypeLen[0] ) { + return lengthExpr.toString(); + } else { + System.err.println("WARNING: struct array field '"+returnSizeLookupName+"' length '"+Arrays.toString(length)+"' without fixed- nor configured-size: "+type.getDebugString()); + return null; + } + } + private String getPointerArrayLengthExpr(final PointerType type, final String returnSizeLookupName) { + final String cfgVal = cfg.returnedArrayLength(returnSizeLookupName); + if( null != cfgVal ) { + return cfgVal; + } + return null; + } + + private static final String dummyFuncTypeName = "null *"; + private static final Type int32Type = new IntType("int32_t", SizeThunk.INT32, false, CVAttributes.CONST); + // private static final Type int8Type = new IntType("char", SizeThunk.INT8, false, 0); + // private static final Type int8PtrType = new PointerType(SizeThunk.POINTER, int8Type, 0); + private static final String nativeArrayLengthArg = "arrayLength"; + private static final String nativeArrayLengthONE = "1"; + private static final String nativeArrayElemOffsetArg = "elem_offset"; + + private boolean requiresGetCStringLength(final Type fieldType, final String returnSizeLookupName) { + if( !cfg.returnsString(returnSizeLookupName) ) { + return false; + } + final PointerType pointerType = fieldType.asPointer(); + if( null != pointerType ) { + return null == getPointerArrayLengthExpr(pointerType, returnSizeLookupName); + } + return false; + } + + private void generateArrayGetterSetterCode(final Set<MethodBinding> methodBindingSet, + final PrintWriter javaWriter, final PrintWriter jniWriter, + final String structCTypeName, final String structClassPkgName, + final Type containingCType, final JavaType containingJType, + final int i, final Field field, final String fieldName, final String returnSizeLookupName) throws Exception { + final Type fieldType = field.getType(); + final JavaType javaType; + try { + javaType = typeToJavaType(fieldType, machDescJava); + } catch (Exception e) { + throw new RuntimeException("Error occurred while creating array/pointer accessor for field \"" + + returnSizeLookupName + "\", "+fieldType.getDebugString(), e); + } + if( GlueGen.debug() ) { + System.err.printf("SE.ac.%02d: javaType %s%n", (i+1), javaType.getDebugString()); + } + + // + // Collect all required information including considering Opaque types + // + final String containingJTypeName = containingJType.getName(); + final boolean isOpaque = isOpaque(fieldType); + final boolean isString = cfg.returnsString(returnSizeLookupName); // FIXME: Allow custom Charset ? US-ASCII, UTF-8 or UTF-16 ? + final boolean useGetCStringLength; + final String arrayLengthExpr; + final int[] arrayLengths; + final boolean useFixedTypeLen[] = { false }; + final boolean isPointer; + final boolean isPrimitive; + final boolean isConst; + final JavaType baseJElemType; + final String baseJElemTypeName; + final boolean hasSingleElement; + final String capitalFieldName; + final String baseJElemTypeNameC; + final String baseJElemTypeNameU; + final boolean isByteBuffer; + { + final Type baseCElemType; + final ArrayType arrayType = fieldType.asArray(); + String _arrayLengthExpr = null; + if( isOpaque || javaType.isPrimitive() ) { + // Overridden by JavaConfiguration.typeInfo(..), i.e. Opaque! + // Emulating array w/ 1 element + isPrimitive = true; + _arrayLengthExpr = nativeArrayLengthONE; + arrayLengths = new int[] { 1 }; + baseCElemType = null; + isPointer = false; + isConst = fieldType.isConst(); + baseJElemType = null; + baseJElemTypeName = compatiblePrimitiveJavaTypeName(fieldType, javaType, machDescJava); + } else { + if( null != arrayType ) { + final int[][] lengthRes = new int[1][]; + _arrayLengthExpr = getArrayArrayLengthExpr(arrayType, returnSizeLookupName, useFixedTypeLen, lengthRes); + arrayLengths = lengthRes[0]; + baseCElemType = arrayType.getBaseElementType(); + isPointer = false; + } else { + final PointerType pointerType = fieldType.asPointer(); + _arrayLengthExpr = getPointerArrayLengthExpr(pointerType, returnSizeLookupName); + arrayLengths = null; + baseCElemType = pointerType.getBaseElementType(); + isPointer = true; + if( 1 != pointerType.pointerDepth() ) { + javaWriter.println(); + final String msg = "SKIP ptr-ptr (depth "+pointerType.pointerDepth()+"): "+returnSizeLookupName +": "+fieldType; + javaWriter.println(" // "+msg); + System.err.println("WARNING: "+msg); + return; + } + } + if( GlueGen.debug() ) { + System.err.printf("SE.ac.%02d: baseCType %s%n", (i+1), baseCElemType.getDebugString()); + } + isPrimitive = baseCElemType.isPrimitive(); + isConst = baseCElemType.isConst(); + try { + baseJElemType = typeToJavaType(baseCElemType, machDescJava); + } catch (Exception e ) { + throw new RuntimeException("Error occurred while creating array/pointer accessor for field \"" + + returnSizeLookupName + "\", baseType "+baseCElemType.getDebugString()+", topType "+fieldType.getDebugString(), e); + } + baseJElemTypeName = baseJElemType.getName(); + + if( baseCElemType.isPrimitive() && !baseCElemType.getSize().hasFixedNativeSize() ) { + javaWriter.println(); + final String msg = "SKIP primitive w/ platform dependent sized type in struct: "+returnSizeLookupName+": "+fieldType.getDebugString(); + javaWriter.println(" // "+msg); + System.err.println("WARNING: "+msg); + return; + } + } + if( GlueGen.debug() ) { + System.err.printf("SE.ac.%02d: baseJElemType %s%n", (i+1), (null != baseJElemType ? baseJElemType.getDebugString() : null)); + } + capitalFieldName = capitalizeString(fieldName); + baseJElemTypeNameC = capitalizeString(baseJElemTypeName); + baseJElemTypeNameU = baseJElemTypeName.toUpperCase(); + isByteBuffer = "Byte".equals(baseJElemTypeNameC); + if( null == _arrayLengthExpr && isString && isPointer ) { + useGetCStringLength = true; + _arrayLengthExpr = "getCStringLengthImpl(pString)+1"; + this.requiresStaticInitialization = true; + LOG.log(INFO, "StaticInit Trigger.3 \"{0}\"", returnSizeLookupName); + } else { + useGetCStringLength = false; + } + arrayLengthExpr = _arrayLengthExpr; + if( null == arrayLengthExpr ) { + javaWriter.println(); + final String msg = "SKIP unsized array in struct: "+returnSizeLookupName+": "+fieldType.getDebugString(); + javaWriter.println(" // "+msg); + System.err.println("WARNING: "+msg); + return; + } + boolean _hasSingleElement=false; + try { + _hasSingleElement = 1 ==Integer.parseInt(_arrayLengthExpr); + } catch (Exception e ) {} + hasSingleElement = _hasSingleElement; + } + if( GlueGen.debug() ) { + System.err.printf("SE.ac.%02d: baseJElemTypeName %s, array-lengths %s%n", (i+1), baseJElemTypeName, Arrays.toString(arrayLengths)); + System.err.printf("SE.ac.%02d: arrayLengthExpr: %s, hasSingleElement %b, isByteBuffer %b, isString %b, isPointer %b, isPrimitive %b, isOpaque %b, isConst %b, useGetCStringLength %b%n", + (i+1), arrayLengthExpr, hasSingleElement, isByteBuffer, isString, isPointer, isPrimitive, isOpaque, isConst, useGetCStringLength); + } + + // + // Emit .. + // + if( !hasSingleElement && useFixedTypeLen[0] ) { + javaWriter.println(); + generateGetterSignature(javaWriter, fieldType, false, "final int", capitalFieldName+"ArrayLength", null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" return "+arrayLengthExpr+";"); + javaWriter.println(" }"); + } + if( !isConst ) { + // Setter + javaWriter.println(); + if( isPrimitive ) { + // Setter Primitive + if( isPointer ) { + // Setter Primitive Pointer + final String msg = "SKIP setter for primitive-pointer type in struct: "+returnSizeLookupName+": "+fieldType.getDebugString(); + javaWriter.println(" // "+msg); + System.err.println("INFO: "+msg); + } else { + // Setter Primitive Array + if( hasSingleElement ) { + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capitalFieldName, null, baseJElemTypeName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" accessor.set" + baseJElemTypeNameC + "At(" + fieldName+"_offset[mdIdx], val);"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + } else { + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capitalFieldName, "final int offset", baseJElemTypeName+"[]", null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" if( offset + val.length > arrayLength ) { throw new IndexOutOfBoundsException(\"offset \"+offset+\" + val.length \"+val.length+\" > array-length \"+arrayLength); };"); + javaWriter.println(" final int elemSize = Buffers.SIZEOF_"+baseJElemTypeNameU+";"); + javaWriter.println(" final ByteBuffer destB = getBuffer();"); + javaWriter.println(" final int bTotal = arrayLength * elemSize;"); + javaWriter.println(" if( bTotal > "+fieldName+"_size[mdIdx] ) { throw new IndexOutOfBoundsException(\"bTotal \"+bTotal+\" > size \"+"+fieldName+"_size[mdIdx]+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" int bOffset = "+fieldName+"_offset[mdIdx];"); + javaWriter.println(" final int bLimes = bOffset + bTotal;"); + javaWriter.println(" if( bLimes > destB.limit() ) { throw new IndexOutOfBoundsException(\"bLimes \"+bLimes+\" > buffer.limit \"+destB.limit()+\", elemOff \"+bOffset+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" bOffset += elemSize * offset;"); + javaWriter.println(" accessor.set" + baseJElemTypeNameC + "sAt(bOffset, val);"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + } + } + } else { + // Setter Struct + if( isPointer ) { + // Setter Struct Pointer + final String msg = "SKIP setter for complex-pointer type in struct: "+returnSizeLookupName+": "+fieldType.getDebugString(); + javaWriter.println(" // "+msg); + System.err.println("INFO: "+msg); + } else { + // Setter Struct Array + if( hasSingleElement ) { + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capitalFieldName, null, baseJElemTypeName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int elemSize = "+baseJElemTypeName+".size();"); + javaWriter.println(" final ByteBuffer destB = getBuffer();"); + javaWriter.println(" if( elemSize > "+fieldName+"_size[mdIdx] ) { throw new IndexOutOfBoundsException(\"elemSize \"+elemSize+\" > size \"+"+fieldName+"_size[mdIdx]); };"); + javaWriter.println(" int bOffset = "+fieldName+"_offset[mdIdx];"); + javaWriter.println(" final int bLimes = bOffset + elemSize;"); + javaWriter.println(" if( bLimes > destB.limit() ) { throw new IndexOutOfBoundsException(\"bLimes \"+bLimes+\" > buffer.limit \"+destB.limit()+\", elemOff \"+bOffset+\", elemSize \"+elemSize); };"); + javaWriter.println(" final ByteBuffer sourceB = val.getBuffer();"); + javaWriter.println(" for(int f=0; f<elemSize; f++) {"); + javaWriter.println(" if( bOffset >= bLimes ) { throw new IndexOutOfBoundsException(\"elem-byte[0][\"+f+\"]: bOffset \"+bOffset+\" >= bLimes \"+bLimes+\", elemSize \"+elemSize); };"); + javaWriter.println(" destB.put(bOffset++, sourceB.get(f));"); + javaWriter.println(" }"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + } else { + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capitalFieldName, "final int offset", baseJElemTypeName+"[]", null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" if( offset + val.length > arrayLength ) { throw new IndexOutOfBoundsException(\"offset \"+offset+\" + val.length \"+val.length+\" > array-length \"+arrayLength); };"); + javaWriter.println(" final int elemSize = "+baseJElemTypeName+".size();"); + javaWriter.println(" final ByteBuffer destB = getBuffer();"); + javaWriter.println(" final int bTotal = arrayLength * elemSize;"); + javaWriter.println(" if( bTotal > "+fieldName+"_size[mdIdx] ) { throw new IndexOutOfBoundsException(\"bTotal \"+bTotal+\" > size \"+"+fieldName+"_size[mdIdx]+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" int bOffset = "+fieldName+"_offset[mdIdx];"); + javaWriter.println(" final int bLimes = bOffset + bTotal;"); + javaWriter.println(" if( bLimes > destB.limit() ) { throw new IndexOutOfBoundsException(\"bLimes \"+bLimes+\" > buffer.limit \"+destB.limit()+\", elemOff \"+bOffset+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" bOffset += elemSize * offset;"); + javaWriter.println(" for(int index=0; index<val.length; index++) {"); + javaWriter.println(" final ByteBuffer sourceB = val[index].getBuffer();"); + javaWriter.println(" for(int f=0; f<elemSize; f++) {"); + javaWriter.println(" if( bOffset >= bLimes ) { throw new IndexOutOfBoundsException(\"elem-byte[\"+(offset+index)+\"][\"+f+\"]: bOffset \"+bOffset+\" >= bLimes \"+bLimes+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" destB.put(bOffset++, sourceB.get(f));"); + javaWriter.println(" }"); + javaWriter.println(" }"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + javaWriter.println(); + generateSetterSignature(javaWriter, fieldType, false, containingJTypeName, capitalFieldName, "final int index", baseJElemTypeName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" final int elemSize = "+baseJElemTypeName+".size();"); + javaWriter.println(" final ByteBuffer destB = getBuffer();"); + javaWriter.println(" final int bTotal = arrayLength * elemSize;"); + javaWriter.println(" if( bTotal > "+fieldName+"_size[mdIdx] ) { throw new IndexOutOfBoundsException(\"bTotal \"+bTotal+\" > size \"+"+fieldName+"_size[mdIdx]+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" int bOffset = "+fieldName+"_offset[mdIdx];"); + javaWriter.println(" final int bLimes = bOffset + bTotal;"); + javaWriter.println(" if( bLimes > destB.limit() ) { throw new IndexOutOfBoundsException(\"bLimes \"+bLimes+\" > buffer.limit \"+destB.limit()+\", elemOff \"+bOffset+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" bOffset += elemSize * index;"); + javaWriter.println(" final ByteBuffer sourceB = val.getBuffer();"); + javaWriter.println(" for(int f=0; f<elemSize; f++) {"); + javaWriter.println(" if( bOffset >= bLimes ) { throw new IndexOutOfBoundsException(\"elem-byte[\"+index+\"][\"+f+\"]: bOffset \"+bOffset+\" >= bLimes \"+bLimes+\", elemSize \"+elemSize+\" * \"+arrayLength); };"); + javaWriter.println(" destB.put(bOffset++, sourceB.get(f));"); + javaWriter.println(" }"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + } + } + } + } + // Getter + javaWriter.println(); + if( isPrimitive ) { + // Getter Primitive + if( isPointer ) { + // Getter Primitive Pointer + final FunctionType ft = new FunctionType(dummyFuncTypeName, SizeThunk.POINTER, fieldType, 0); + ft.addArgument(containingCType.getCVVariant(containingCType.getCVAttributes() | CVAttributes.CONST), + CMethodBindingEmitter.cThisArgumentName()); + ft.addArgument(int32Type, nativeArrayLengthArg); + final FunctionSymbol fs = new FunctionSymbol("get"+capitalFieldName, ft); + jniWriter.println(); + jniWriter.print("static "+fs.toString()); + jniWriter.println("{"); + jniWriter.println(" return "+CMethodBindingEmitter.cThisArgumentName()+"->"+field.getName()+";"); + jniWriter.println("}"); + jniWriter.println(); + generateArrayPointerCode(methodBindingSet, javaWriter, jniWriter, structCTypeName, structClassPkgName, + containingCType, containingJType, i, fs, returnSizeLookupName, arrayLengthExpr, nativeArrayLengthArg); + javaWriter.println(); + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeNameC+"Buffer", capitalFieldName, null, arrayLengthExpr); + javaWriter.println(" {"); + if( useGetCStringLength ) { + javaWriter.println(" final int arrayLength = get"+capitalFieldName+"ArrayLength();"); + } else { + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + } + javaWriter.println(" final ByteBuffer _res = get"+capitalFieldName+"0(getBuffer(), arrayLength);"); + javaWriter.println(" if (_res == null) return null;"); + javaWriter.print(" return Buffers.nativeOrder(_res)"); + if( !isByteBuffer ) { + javaWriter.print(".as"+baseJElemTypeNameC+"Buffer()"); + } + javaWriter.println(";"); + javaWriter.println(" }"); + if( isString && isByteBuffer ) { + javaWriter.println(); + generateGetterSignature(javaWriter, fieldType, false, "String", capitalFieldName+"AsString", null, arrayLengthExpr); + javaWriter.println(" {"); + if( useGetCStringLength ) { + javaWriter.println(" final int arrayLength = get"+capitalFieldName+"ArrayLength();"); + } else { + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + } + javaWriter.println(" final ByteBuffer bb = get"+capitalFieldName+"0(getBuffer(), arrayLength);"); + javaWriter.println(" if (bb == null) return null;"); + javaWriter.println(" final byte[] ba = new byte[arrayLength];"); + javaWriter.println(" int i = -1;"); + javaWriter.println(" while( ++i < arrayLength ) {"); + javaWriter.println(" ba[i] = bb.get(i);"); + javaWriter.println(" if( (byte)0 == ba[i] ) break;"); + javaWriter.println(" }"); + javaWriter.println(" return new String(ba, 0, i);"); + javaWriter.println(" }"); + } + if( useGetCStringLength ) { + javaWriter.println(); + generateGetterSignature(javaWriter, fieldType, false, "final int", capitalFieldName+"ArrayLength", null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final long pString = PointerBuffer.wrap( accessor.slice(" + fieldName+"_offset[mdIdx], PointerBuffer.ELEMENT_SIZE) ).get(0);"); + javaWriter.println(" return "+arrayLengthExpr+";"); + javaWriter.println(" }"); + } + } else { + // Getter Primitive Array + if( hasSingleElement ) { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName, capitalFieldName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" return accessor.get" + baseJElemTypeNameC + "At(" + fieldName+"_offset[mdIdx]);"); + javaWriter.println(" }"); + javaWriter.println(); + } else { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeNameC+"Buffer", capitalFieldName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.print(" return accessor.slice(" + fieldName+"_offset[mdIdx], Buffers.SIZEOF_"+baseJElemTypeNameU+" * "+arrayLengthExpr+")"); + if( !isByteBuffer ) { + javaWriter.print(".as"+baseJElemTypeNameC+"Buffer()"); + } + javaWriter.println(";"); + javaWriter.println(" }"); + javaWriter.println(); + if( isString && isByteBuffer ) { + generateGetterSignature(javaWriter, fieldType, false, "String", capitalFieldName+"AsString", null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int offset = " + fieldName+"_offset[mdIdx];"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" final ByteBuffer bb = getBuffer();"); + javaWriter.println(" final byte[] ba = new byte[arrayLength];"); + javaWriter.println(" int i = -1;"); + javaWriter.println(" while( ++i < arrayLength ) {"); + javaWriter.println(" ba[i] = bb.get(offset+i);"); + javaWriter.println(" if( (byte)0 == ba[i] ) break;"); + javaWriter.println(" }"); + javaWriter.println(" return new String(ba, 0, i);"); + javaWriter.println(" }"); + } else { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName+"[]", capitalFieldName, "final int offset, "+baseJElemTypeName+" result[]", arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" if( offset + result.length > arrayLength ) { throw new IndexOutOfBoundsException(\"offset \"+offset+\" + result.length \"+result.length+\" > array-length \"+arrayLength); };"); + javaWriter.println(" return accessor.get" + baseJElemTypeNameC + "sAt(" + fieldName+"_offset[mdIdx] + (Buffers.SIZEOF_"+baseJElemTypeNameU+" * offset), result);"); + javaWriter.println(" }"); + javaWriter.println(); + } + } + } + } else { + // Getter Struct + if( isPointer ) { + // Getter Struct Pointer + final FunctionType ft = new FunctionType(dummyFuncTypeName, SizeThunk.POINTER, fieldType, 0); + ft.addArgument(containingCType.getCVVariant(containingCType.getCVAttributes() | CVAttributes.CONST), + CMethodBindingEmitter.cThisArgumentName()); + ft.addArgument(int32Type, nativeArrayElemOffsetArg); + final FunctionSymbol fs = new FunctionSymbol("get"+capitalFieldName, ft); + jniWriter.println(); + jniWriter.print("static "+fs.toString()); + jniWriter.println("{"); + jniWriter.println(" return "+CMethodBindingEmitter.cThisArgumentName()+"->"+field.getName()+"+"+nativeArrayElemOffsetArg+";"); + jniWriter.println("}"); + jniWriter.println(); + generateArrayPointerCode(methodBindingSet, javaWriter, jniWriter, structCTypeName, structClassPkgName, + containingCType, containingJType, i, fs, returnSizeLookupName, arrayLengthExpr, nativeArrayLengthONE); + javaWriter.println(); + if( hasSingleElement ) { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName, capitalFieldName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final ByteBuffer source = getBuffer();"); + javaWriter.println(" final ByteBuffer _res = get"+capitalFieldName+"0(source, 0);"); + javaWriter.println(" if (_res == null) return null;"); + javaWriter.println(" return "+baseJElemTypeName+".create(_res);"); + javaWriter.println(" }"); + } else { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName+"[]", capitalFieldName, "final int offset, "+baseJElemTypeName+" result[]", arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" if( offset + result.length > arrayLength ) { throw new IndexOutOfBoundsException(\"offset \"+offset+\" + result.length \"+result.length+\" > array-length \"+arrayLength); };"); + javaWriter.println(" final ByteBuffer source = getBuffer();"); + javaWriter.println(" for(int index=0; index<result.length; index++) {"); + javaWriter.println(" final ByteBuffer _res = get"+capitalFieldName+"0(source, offset+index);"); + javaWriter.println(" if (_res == null) return null;"); + javaWriter.println(" result[index] = "+baseJElemTypeName+".create(_res);"); + javaWriter.println(" }"); + javaWriter.println(" return result;"); + javaWriter.println(" }"); + } + } else { + // Getter Struct Array + if( hasSingleElement ) { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName, capitalFieldName, null, arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" return "+baseJElemTypeName+".create(accessor.slice("+fieldName+"_offset[mdIdx], "+baseJElemTypeName+".size()));"); + javaWriter.println(" }"); + } else { + generateGetterSignature(javaWriter, fieldType, false, baseJElemTypeName+"[]", capitalFieldName, "final int offset, "+baseJElemTypeName+" result[]", arrayLengthExpr); + javaWriter.println(" {"); + javaWriter.println(" final int arrayLength = "+arrayLengthExpr+";"); + javaWriter.println(" if( offset + result.length > arrayLength ) { throw new IndexOutOfBoundsException(\"offset \"+offset+\" + result.length \"+result.length+\" > array-length \"+arrayLength); };"); + javaWriter.println(" final int elemSize = "+baseJElemTypeName+".size();"); + javaWriter.println(" int bOffset = "+fieldName+"_offset[mdIdx] + ( elemSize * offset );"); + javaWriter.println(" for(int index=0; index<result.length; index++) {"); + javaWriter.println(" result[index] = "+baseJElemTypeName+".create(accessor.slice(bOffset, elemSize));"); + javaWriter.println(" bOffset += elemSize;"); + javaWriter.println(" }"); + javaWriter.println(" return result;"); + javaWriter.println(" }"); + } + } + } + } + + private static final boolean DEBUG_TYPEC2JAVA = false; + private JavaType typeToJavaType(final Type cType, final MachineDescription curMachDesc) { + final JavaType jt = typeToJavaTypeImpl(cType, curMachDesc); + if( DEBUG_TYPEC2JAVA ) { + System.err.println("typeToJavaType: "+cType.getDebugString()+" -> "+jt.getDebugString()); + } + return jt; + } + private boolean isJNIEnvPointer(final Type cType) { + final PointerType opt = cType.asPointer(); + return (opt != null) && + (opt.getTargetType().getName() != null) && + (opt.getTargetType().getName().equals("JNIEnv")); + } + private JavaType typeToJavaTypeImpl(final Type cType, final MachineDescription curMachDesc) { // Recognize JNIEnv* case up front - PointerType opt = cType.asPointer(); - if ((opt != null) && - (opt.getTargetType().getName() != null) && - (opt.getTargetType().getName().equals("JNIEnv"))) { - return JavaType.createForJNIEnv(); + if( isJNIEnvPointer(cType) ) { + return JavaType.createForJNIEnv(); } - Type t = cType; - // Opaque specifications override automatic conversions // in case the identity is being used .. not if ptr-ptr - TypeInfo info = cfg.typeInfo(t, typedefDictionary); + final TypeInfo info = cfg.typeInfo(cType, typedefDictionary); if (info != null) { boolean isPointerPointer = false; - if (t.pointerDepth() > 0 || t.arrayDimension() > 0) { + if (cType.pointerDepth() > 0 || cType.arrayDimension() > 0) { Type targetType; // target type - if (t.isPointer()) { + if (cType.isPointer()) { // t is <type>*, we need to get <type> - targetType = t.asPointer().getTargetType(); + targetType = cType.asPointer().getTargetType(); } else { // t is <type>[], we need to get <type> - targetType = t.asArray().getBaseElementType(); + targetType = cType.asArray().getBaseElementType(); } - if (t.pointerDepth() == 2 || t.arrayDimension() == 2) { + if (cType.pointerDepth() == 2 || cType.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) @@ -1369,7 +1953,9 @@ public class JavaEmitter implements GlueEmitter { // t is<type>**, targetType is <type>*, we need to get <type> Type bottomType = targetType.asPointer().getTargetType(); - LOG.log(INFO, "Opaque Type: {0}, targetType: {1}, bottomType: {2} is ptr-ptr", new Object[]{t, targetType, bottomType}); + if( GlueGen.debug() ) { + LOG.log(INFO, "Opaque Type: {0}, targetType: {1}, bottomType: {2} is ptr-ptr", new Object[]{cType.getDebugString(), targetType, bottomType}); + } } } } @@ -1378,35 +1964,35 @@ public class JavaEmitter implements GlueEmitter { } } - if (t.isInt() || t.isEnum()) { - switch ((int) t.getSize(curMachDesc)) { + if (cType.isInt() || cType.isEnum()) { + switch ((int) cType.getSize(curMachDesc)) { case 1: return javaType(Byte.TYPE); case 2: return javaType(Short.TYPE); case 4: return javaType(Integer.TYPE); case 8: return javaType(Long.TYPE); default: throw new RuntimeException("Unknown integer type of size " + - t.getSize(curMachDesc) + " and name " + t.getName()); + cType.getSize(curMachDesc) + " and name " + cType.getName()); } - } else if (t.isFloat()) { + } else if (cType.isFloat()) { return javaType(Float.TYPE); - } else if (t.isDouble()) { + } else if (cType.isDouble()) { return javaType(Double.TYPE); - } else if (t.isVoid()) { + } else if (cType.isVoid()) { return javaType(Void.TYPE); - } else if (t.pointerDepth() > 0 || t.arrayDimension() > 0) { + } else if (cType.pointerDepth() > 0 || cType.arrayDimension() > 0) { Type targetType; // target type - if (t.isPointer()) { + if (cType.isPointer()) { // t is <type>*, we need to get <type> - targetType = t.asPointer().getTargetType(); + targetType = cType.asPointer().getTargetType(); } else { // t is <type>[], we need to get <type> - targetType = t.asArray().getBaseElementType(); + targetType = cType.asArray().getBaseElementType(); } // 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 || t.arrayDimension() == 1) { + if (cType.pointerDepth() == 1 || cType.arrayDimension() == 1) { if (targetType.isVoid()) { return JavaType.createForCVoidPointer(); } else if (targetType.isInt()) { @@ -1421,39 +2007,39 @@ public class JavaEmitter implements GlueEmitter { case 4: return JavaType.createForCInt32Pointer(); case 8: return JavaType.createForCInt64Pointer(); default: throw new RuntimeException("Unknown integer array type of size " + - t.getSize(curMachDesc) + " and name " + t.getName()); + cType.getSize(curMachDesc) + " and name " + cType.getName()+", "+cType.getDebugString()); } } else if (targetType.isFloat()) { return JavaType.createForCFloatPointer(); } else if (targetType.isDouble()) { return JavaType.createForCDoublePointer(); } else if (targetType.isCompound()) { - if (t.isArray()) { // FIXME: Compound and Compound-Arrays + if (cType.isArray()) { // FIXME: Compound and Compound-Arrays return JavaType.createForCArray(targetType); } // Special cases for known JNI types (in particular for converting jawt.h) - if (t.getName() != null && - t.getName().equals("jobject")) { + if (cType.getName() != null && + cType.getName().equals("jobject")) { return javaType(java.lang.Object.class); } String name = targetType.getName(); if (name == null) { // Try containing pointer type for any typedefs - name = t.getName(); + name = cType.getName(); if (name == null) { - throw new RuntimeException("Couldn't find a proper type name for pointer type " + t); + throw new RuntimeException("Couldn't find a proper type name for pointer type " + cType.getDebugString()); } } return JavaType.createForCStruct(cfg.renameJavaType(name)); } else { throw new RuntimeException("Don't know how to convert pointer/array type \"" + - t + "\""); + cType.getDebugString() + "\""); } } // Handle Types of form pointer-to-pointer-to-type or // array-of-arrays-of-type, like char** or int[][] - else if (t.pointerDepth() == 2 || t.arrayDimension() == 2) { + else if (cType.pointerDepth() == 2 || cType.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) @@ -1461,11 +2047,21 @@ public class JavaEmitter implements GlueEmitter { if (targetType.isPointer()) { // t is<type>**, targetType is <type>*, we need to get <type> bottomType = targetType.asPointer().getTargetType(); + if( GlueGen.debug() ) { + LOG.log(INFO, "typeToJavaType(ptr-ptr): {0}, targetType: {1}, bottomType: {2}", new Object[]{cType.getDebugString(), targetType, bottomType}); + } return JavaType.forNIOPointerBufferClass(); - } else { + } else if(targetType.isArray()) { // t is<type>[][], targetType is <type>[], we need to get <type> bottomType = targetType.asArray().getBaseElementType(); - LOG.log(WARNING, "typeToJavaType(ptr-ptr): {0}, targetType: {1}, bottomType: {2} -> Unhandled!", new Object[]{t, targetType, bottomType}); + if( GlueGen.debug() ) { + LOG.log(INFO, "typeToJavaType(ptr-ptr.array): {0}, targetType: {1}, bottomType: {2}", new Object[]{cType.getDebugString(), targetType, bottomType}); + } + } else { + bottomType = targetType; + if( GlueGen.debug() ) { + LOG.log(INFO, "typeToJavaType(ptr-ptr.primitive): {0}, targetType: {1}, bottomType: {2}", new Object[]{cType.getDebugString(), targetType, bottomType}); + } } // Warning: The below code is not backed up by an implementation, @@ -1479,14 +2075,14 @@ public class JavaEmitter implements GlueEmitter { 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(curMachDesc) + " and name " + bottomType.getName()); + bottomType.getSize(curMachDesc) + " and name " + bottomType.getName()+", "+bottomType.getDebugString()); } } 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() + + throw new RuntimeException("Unexpected primitive type " + bottomType.getDebugString() + " in two-dimensional array"); } } else if (bottomType.isVoid()) { @@ -1497,7 +2093,7 @@ public class JavaEmitter implements GlueEmitter { return JavaType.createForCArray(bottomType); } else { throw new RuntimeException( - "Could not convert C type \"" + t + "\" " + + "Could not convert C type \"" + cType.getDebugString() + "\" " + "to appropriate Java type; need to add more support for " + "depth=2 pointer/array types [debug info: targetType=\"" + targetType + "\"]"); @@ -1505,23 +2101,23 @@ public class JavaEmitter implements GlueEmitter { } else { // can't handle this type of pointer/array argument throw new RuntimeException( - "Could not convert C pointer/array \"" + t + "\" to " + + "Could not convert C pointer/array \"" + cType.getDebugString() + "\" to " + "appropriate Java type; types with pointer/array depth " + "greater than 2 are not yet supported [debug info: " + - "pointerDepth=" + t.pointerDepth() + " arrayDimension=" + - t.arrayDimension() + " targetType=\"" + targetType + "\"]"); + "pointerDepth=" + cType.pointerDepth() + " arrayDimension=" + + cType.arrayDimension() + " targetType=\"" + targetType + "\"]"); } - } else if(t.isCompound() ) { // FIXME: Compound and Compound-Arrays - final String name = t.getName(); + } else if(cType.isCompound() ) { // FIXME: Compound and Compound-Arrays + final String name = cType.getName(); if (name == null) { - throw new RuntimeException("Couldn't find a proper type name for pointer type " + t); + throw new RuntimeException("Couldn't find a proper type name for pointer type " + cType.getDebugString()); } return JavaType.createForCStruct(cfg.renameJavaType(name)); } else { throw new RuntimeException( - "Could not convert C type \"" + t + "\" (class " + - t.getClass().getName() + ") to appropriate Java type"); + "Could not convert C type \"" + cType.getDebugString() + "\" (class " + + cType.getClass().getName() + ") to appropriate Java type"); } } @@ -1897,6 +2493,10 @@ public class JavaEmitter implements GlueEmitter { cWriter.println(" return _initClazzAccess(env);"); cWriter.println("}"); cWriter.println(); + cWriter.println("JNIEXPORT jint JNICALL "+JavaEmitter.getJNIMethodNamePrefix(packageName, className)+"_getCStringLengthImpl(JNIEnv *env, jclass _unused, jlong pString) {"); + cWriter.println(" return 0 != pString ? strlen((const char*)(intptr_t)pString) : 0;"); + cWriter.println("}"); + cWriter.println(); } } @@ -1905,6 +2505,9 @@ public class JavaEmitter implements GlueEmitter { jWriter.println(); jWriter.println(" private static native boolean initializeImpl();"); jWriter.println(); + jWriter.println(); + jWriter.println(" private static native int getCStringLengthImpl(final long pString);"); + jWriter.println(); if( !cfg.manualStaticInitCall(className) ) { jWriter.println(staticClassInitCallJavaCode); } @@ -1958,7 +2561,7 @@ public class JavaEmitter implements GlueEmitter { } binding.setJavaReturnType(javaType(java.lang.String.class)); } else { - binding.setJavaReturnType(typeToJavaType(sym.getReturnType(), false, curMachDesc)); + binding.setJavaReturnType(typeToJavaType(sym.getReturnType(), curMachDesc)); } // System.out.println("bindFunction(1) "+binding.getJavaReturnType()); @@ -1969,7 +2572,7 @@ public class JavaEmitter implements GlueEmitter { for (int i = 0; i < sym.getNumArguments(); i++) { Type cArgType = sym.getArgumentType(i); - JavaType mappedType = typeToJavaType(cArgType, true, curMachDesc); + JavaType mappedType = typeToJavaType(cArgType, curMachDesc); // System.out.println("C arg type -> \"" + cArgType + "\"" ); // System.out.println(" Java -> \"" + mappedType + "\"" ); @@ -2147,5 +2750,4 @@ public class JavaEmitter implements GlueEmitter { private final String capitalizeString(String string) { return Character.toUpperCase(string.charAt(0)) + string.substring(1); } - } diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java index c651114..ea7910a 100644 --- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java @@ -41,9 +41,7 @@ package com.jogamp.gluegen; import com.jogamp.gluegen.cgram.HeaderParser; import com.jogamp.gluegen.cgram.types.ArrayType; -import com.jogamp.gluegen.cgram.types.CompoundType; import com.jogamp.gluegen.cgram.types.EnumType; -import com.jogamp.gluegen.cgram.types.PointerType; import com.jogamp.gluegen.cgram.types.Type; import java.io.PrintWriter; @@ -93,6 +91,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { // incoming Java arguments as parameters and computing as an int the // number of elements of the returned array. private String returnedArrayLengthExpression; + private boolean returnedArrayLengthExpressionOnlyForComments = false; // A suffix used to create a temporary outgoing array of Buffers to // represent an array of compound type wrappers @@ -154,6 +153,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { prologue = arg.prologue; epilogue = arg.epilogue; returnedArrayLengthExpression = arg.returnedArrayLengthExpression; + returnedArrayLengthExpressionOnlyForComments = arg.returnedArrayLengthExpressionOnlyForComments; cfg = arg.cfg; } @@ -192,6 +192,17 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { arguments. */ public void setReturnedArrayLengthExpression(String expr) { returnedArrayLengthExpression = expr; + returnedArrayLengthExpressionOnlyForComments = false; + } + protected void setReturnedArrayLengthExpression(String expr, boolean onlyForComments) { + returnedArrayLengthExpression = expr; + returnedArrayLengthExpressionOnlyForComments = onlyForComments; + } + protected String getReturnedArrayLengthExpression() { + return returnedArrayLengthExpressionOnlyForComments ? null : returnedArrayLengthExpression; + } + protected String getReturnedArrayLengthComment() { + return returnedArrayLengthExpression; } /** Sets the manually-generated prologue code for this emitter. */ @@ -278,6 +289,9 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } } String name = type.getName(); + if( null == name ) { + throw new IllegalArgumentException("null type name: "+type.getDebugString()); + } int index = name.lastIndexOf('.')+1; // always >= 0 name = name.substring(index); @@ -389,7 +403,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { return byteOffsetArgName(getArgumentName(i)); } - protected String byteOffsetArgName(String s) { + protected static String byteOffsetArgName(String s) { return s + "_byte_offset"; } @@ -715,38 +729,9 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { JavaType returnType = binding.getJavaReturnType(); if (returnType.isCompoundTypeWrapper()) { - String fmt = getReturnedArrayLengthExpression(); + // Details are handled in JavaEmitter's struct handling! writer.println(" if (_res == null) return null;"); - if (fmt == null) { - writer.print(" return " + returnType.getName() + ".create(Buffers.nativeOrder(_res))"); - } else { - writer.println(" Buffers.nativeOrder(_res);"); - String expr = new MessageFormat(fmt).format(argumentNameArray()); - PointerType cReturnTypePointer = binding.getCReturnType().asPointer(); - CompoundType cReturnType = null; - if (cReturnTypePointer != null) { - cReturnType = cReturnTypePointer.getTargetType().asCompound(); - } - if (cReturnType == null) { - throw new RuntimeException("ReturnedArrayLength directive currently only supported for pointers to compound types " + - "(error occurred while generating Java glue code for " + getName() + ")"); - } - writer.println(" final " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[" + expr + "];"); - writer.println(" for (int _count = 0; _count < " + expr + "; _count++) {"); - // Create temporary ByteBuffer slice - // FIXME: probably need Type.getAlignedSize() for arrays of - // compound types (rounding up to machine-dependent alignment) - writer.println(" _res.position(_count * " + getReturnTypeString(true) + ".size());"); - writer.println(" _res.limit ((1 + _count) * " + getReturnTypeString(true) + ".size());"); - writer.println(" final ByteBuffer _tmp = _res.slice();"); - writer.println(" Buffers.nativeOrder(_tmp);"); - writer.println(" _res.position(0);"); - writer.println(" _res.limit(_res.capacity());"); - writer.println(" _retarray[_count] = " + getReturnTypeString(true) + ".create(_tmp);"); - writer.println(" }"); - writer.print (" return _retarray"); - } - writer.println(";"); + writer.println(" return " + returnType.getName() + ".create(Buffers.nativeOrder(_res));"); } else if (returnType.isNIOBuffer()) { writer.println(" if (_res == null) return null;"); writer.println(" Buffers.nativeOrder(_res);"); @@ -821,10 +806,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { @Override protected String getBaseIndentString() { return " "; } - protected String getReturnedArrayLengthExpression() { - return returnedArrayLengthExpression; - } - /** * Class that emits a generic comment for JavaMethodBindingEmitters; the comment * includes the C signature of the native method that is being bound by the @@ -835,6 +816,10 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { public void emit(FunctionEmitter emitter, PrintWriter writer) { emitBeginning(emitter, writer); emitBindingCSignature(((JavaMethodBindingEmitter)emitter).getBinding(), writer); + final String arrayLengthExpr = getReturnedArrayLengthComment(); + if( null != arrayLengthExpr ) { + writer.print(", covering an array of length <code>"+arrayLengthExpr+"</code>"); + } emitEnding(emitter, writer); } protected void emitBeginning(FunctionEmitter emitter, PrintWriter writer) { @@ -889,8 +874,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { protected class InterfaceCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter { @Override - protected void emitBeginning(FunctionEmitter emitter, - PrintWriter writer) { + protected void emitBeginning(FunctionEmitter emitter, PrintWriter writer) { writer.print("Interface to C language function: <br> "); } } diff --git a/src/java/com/jogamp/gluegen/JavaType.java b/src/java/com/jogamp/gluegen/JavaType.java index a1cbb01..9091588 100644 --- a/src/java/com/jogamp/gluegen/JavaType.java +++ b/src/java/com/jogamp/gluegen/JavaType.java @@ -60,7 +60,7 @@ public class JavaType { } private final Class<?> clazz; // Primitive types and other types representable as Class objects - private final String name; // Types we're generating glue code for (i.e., C structs) + private final String structName; // Types we're generating glue code for (i.e., C structs) private final Type elementType; // Element type if this JavaType represents a C array private final C_PTR primitivePointerType; @@ -82,8 +82,8 @@ public class JavaType { JavaType t = (JavaType) arg; return (this == t || (t.clazz == clazz && - ((name == null ? t.name == null : name.equals(t.name)) || - ((name != null) && (t.name != null) && (name.equals(t.name)))) && + ((structName == null ? t.structName == null : structName.equals(t.structName)) || + ((structName != null) && (t.structName != null) && (structName.equals(t.structName)))) && ((elementType == t.elementType) || (elementType != null) && (t.elementType != null) && (elementType.equals(t.elementType))) && (primitivePointerType == t.primitivePointerType))); @@ -92,10 +92,10 @@ public class JavaType { @Override public int hashCode() { if (clazz == null) { - if (name == null) { + if (structName == null) { return 0; } - return name.hashCode(); + return structName.hashCode(); } return clazz.hashCode(); } @@ -245,7 +245,7 @@ public class JavaType { if (elementType != null) { return elementType.getName(); } - return name; + return structName; } /** @@ -261,11 +261,14 @@ public class JavaType { } if (elementType != null) { if(elementType.getName()==null) { - throw new RuntimeException("elementType.name is null: "+getDumpString()); + throw new RuntimeException("elementType.name is null: "+getDebugString()); } return "[" + descriptor(elementType.getName()); } - return descriptor(name); + if( null != structName ) { + return descriptor(structName); + } + return "ANON_NIO"; } /** Returns the String corresponding to the JNI type for this type, @@ -432,7 +435,7 @@ public class JavaType { } public boolean isCompoundTypeWrapper() { - return (clazz == null && name != null && !isJNIEnv()); + return (clazz == null && structName != null && !isJNIEnv()); } public boolean isArrayOfCompoundTypeWrappers() { @@ -473,12 +476,12 @@ public class JavaType { } public boolean isJNIEnv() { - return clazz == null && "JNIEnv".equals(name); + return clazz == null && "JNIEnv".equals(structName); } @Override public Object clone() { - return new JavaType(primitivePointerType, clazz, name, elementType); + return new JavaType(primitivePointerType, clazz, structName, elementType); } @Override @@ -497,16 +500,27 @@ public class JavaType { sb.append(val); } // For debugging - public String getDumpString() { + public String getDebugString() { final StringBuilder sb = new StringBuilder(); - sb.append("JavaType["); + sb.append("JType["); boolean prepComma = false; + { + final String javaTypeName = getName(); + if( null != javaTypeName ) { + append(sb, javaTypeName, false); + } else { + append(sb, "ANON", false); + } + sb.append(" / "); + if( null != structName ) { + append(sb, "'"+structName+"'", prepComma); prepComma=true; + } else { + append(sb, "NIL", prepComma); prepComma=true; + } + } if( null != clazz ) { append(sb, "clazz = "+clazz.getName(), prepComma); prepComma=true; } - if( null != name ) { - append(sb, "name = "+name, prepComma); prepComma=true; - } if( null != elementType ) { append(sb, "elementType = "+elementType, prepComma); prepComma=true; } @@ -523,6 +537,15 @@ public class JavaType { if( isCompoundTypeWrapper() ) { append(sb, "compound", prepComma); prepComma=true; } + if( isArray() ) { + append(sb, "array", prepComma); prepComma=true; + } + if( isPrimitive() ) { + append(sb, "primitive", prepComma); prepComma=true; + } + if( isPrimitiveArray() ) { + append(sb, "primitiveArray", prepComma); prepComma=true; + } if( isNIOBuffer() ) { append(sb, "nioBuffer", prepComma); prepComma=true; } @@ -532,7 +555,7 @@ public class JavaType { if( isCPrimitivePointerType() ) { append(sb, "C-Primitive-Pointer", prepComma); prepComma=true; } - sb.append("]]"); + append(sb, "descriptor '"+getDescriptor()+"'", prepComma); prepComma=true; return sb.toString(); } @@ -543,15 +566,15 @@ public class JavaType { private JavaType(Class<?> clazz) { this.primitivePointerType = null; this.clazz = clazz; - this.name = null; + this.structName = null; this.elementType = null; } /** Constructs a type representing a named C struct. */ - private JavaType(String name) { + private JavaType(String structName) { this.primitivePointerType = null; this.clazz = null; - this.name = name; + this.structName = structName; this.elementType = null; } @@ -560,7 +583,7 @@ public class JavaType { private JavaType(C_PTR primitivePointerType) { this.primitivePointerType = primitivePointerType; this.clazz = null; - this.name = null; + this.structName = null; this.elementType = null; } @@ -568,14 +591,15 @@ public class JavaType { private JavaType(Type elementType) { this.primitivePointerType = null; this.clazz = null; - this.name = null; + this.structName = null; this.elementType = elementType; } + /** clone only */ private JavaType(C_PTR primitivePointerType, Class<?> clazz, String name, Type elementType) { this.primitivePointerType = primitivePointerType; this.clazz = clazz; - this.name = name; + this.structName = name; this.elementType = elementType; } diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java index 61732fb..53f6c7d 100644 --- a/src/java/com/jogamp/gluegen/MethodBinding.java +++ b/src/java/com/jogamp/gluegen/MethodBinding.java @@ -436,8 +436,16 @@ public class MethodBinding { computedSignatureProperties = true; } - /** Indicates whether this MethodBinding is for a function pointer - contained in a struct. */ + /** + * Indicates whether this MethodBinding is for a function pointer + * contained in a struct, or to access array- or pointer-data from a struct. + * <p> + * The native calling convention, i.e. via a 'this' function pointer + * or by a static native function must be decided in the + * {@link JavaEmitter} handling structs and + * passed to the {@link CMethodBindingEmitter#setIsCStructFunctionPointer(boolean)}. + * </p> + */ public boolean hasContainingType() { return (getContainingType() != null); } diff --git a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java index 678fa10..401944b 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java @@ -72,8 +72,7 @@ public class ArrayType extends MemoryLayoutType implements Cloneable { // names during parsing // Note: don't think cvAttributes can be set for array types (unlike pointer types) if (computedName == null) { - computedName = elementType.getName() + " *"; - computedName = computedName.intern(); + computedName = (elementType.getName() + " *").intern(); } return computedName; } @@ -85,14 +84,14 @@ public class ArrayType extends MemoryLayoutType implements Cloneable { public int getLength() { return length; } public boolean hasLength() { return length >= 0; } - /** Return the bottommost element type if this is a multidimensional - array. */ + @Override public Type getBaseElementType() { ArrayType t = this; while (t.getElementType().isArray()) { t = t.getElementType().asArray(); } return t.getElementType(); + // return elementType.getBaseElementType(); } /** Recompute the size of this array if necessary. This needs to be diff --git a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java index 70fbc64..7672744 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java @@ -126,19 +126,16 @@ public class FunctionType extends Type implements Cloneable { return toString(null); } - public String toString(String functionName) { + public String toString(final String functionName) { return toString(functionName, false); } - public String toString(String functionName, boolean emitNativeTag) { + public String toString(final String functionName, final boolean emitNativeTag) { return toString(functionName, null, emitNativeTag, false); } - String toString(String functionName, String callingConvention, boolean emitNativeTag, boolean isPointer) { - StringBuilder res = new StringBuilder(); - if(isConst()) { - res.append("const "); - } + String toString(final String functionName, final String callingConvention, final boolean emitNativeTag, final boolean isPointer) { + final StringBuilder res = new StringBuilder(); res.append(getReturnType()); res.append(" "); if (isPointer) { @@ -167,17 +164,11 @@ public class FunctionType extends Type implements Cloneable { Type t = getArgumentType(i); if (t.isFunctionPointer()) { 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) { @@ -190,9 +181,6 @@ public class FunctionType extends Type implements Cloneable { } } res.append(")"); - if (!isPointer) { - res.append(";"); - } return res.toString(); } diff --git a/src/java/com/jogamp/gluegen/cgram/types/PointerType.java b/src/java/com/jogamp/gluegen/cgram/types/PointerType.java index 330d791..5f19202 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/PointerType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/PointerType.java @@ -97,8 +97,7 @@ public class PointerType extends Type implements Cloneable { // Lazy computation of name due to lazy setting of compound type // names during parsing if (computedName == null) { - computedName = targetType.getName(includeCVAttrs) + " *"; - computedName = computedName.intern(); + computedName = (targetType.getName(includeCVAttrs) + " *").intern(); } if (!includeCVAttrs) { return computedName; @@ -120,12 +119,15 @@ public class PointerType extends Type implements Cloneable { return targetType; } - public Type getLastTargetType() { + @Override + public Type getBaseElementType() { + /** if(targetType.isPointer()) { - return ((PointerType)targetType).getLastTargetType(); + return ((PointerType)targetType).getBaseElementType(); } else { return targetType; - } + } */ + return targetType.getBaseElementType(); } @Override diff --git a/src/java/com/jogamp/gluegen/cgram/types/StructLayout.java b/src/java/com/jogamp/gluegen/cgram/types/StructLayout.java index f105f1f..dfcb722 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/StructLayout.java +++ b/src/java/com/jogamp/gluegen/cgram/types/StructLayout.java @@ -87,9 +87,6 @@ public class StructLayout { } else { curOffset = SizeThunk.add(curOffset, sz); } - if( GlueGen.debug() ) { - System.err.printf("SL.%02d: o %03d, s %03d, t %s: %s%n", (i+1), f.getOffset(dbgMD), ft.getSize(dbgMD), ft, f); - } } else if (ft.isCompound()) { final CompoundType ct = ft.asCompound(); if(!ct.isLayouted()) { @@ -103,9 +100,6 @@ public class StructLayout { } else { curOffset = SizeThunk.add(curOffset, sz); } - if( GlueGen.debug() ) { - System.err.printf("SL.%02d: o %03d, s %03d, t %s{%d}: %s%n", (i+1), f.getOffset(dbgMD), ft.getSize(dbgMD), ft, ct.getNumFields(), f); - } } else if (ft.isArray()) { final ArrayType arrayType = ft.asArray(); if(!arrayType.isLayouted()) { @@ -122,9 +116,6 @@ public class StructLayout { curOffset = SizeThunk.align(curOffset, sz); f.setOffset(curOffset); curOffset = SizeThunk.add(curOffset, sz); - if( GlueGen.debug() ) { - System.err.printf("SL.%02d: o %03d, s %03d, t %s: %s%n", (i+1), f.getOffset(dbgMD), ft.getSize(dbgMD), ft, f); - } } else { // FIXME String name = t.getName(); @@ -136,6 +127,9 @@ public class StructLayout { " in type " + name + ") not implemented yet"); } + if( GlueGen.debug() ) { + System.err.printf("SL.%02d: o %03d, s %03d: %s, %s%n", (i+1), f.getOffset(dbgMD), ft.getSize(dbgMD), f, ft.getDebugString()); + } } if (t.isUnion()) { t.setSize(maxSize); diff --git a/src/java/com/jogamp/gluegen/cgram/types/Type.java b/src/java/com/jogamp/gluegen/cgram/types/Type.java index a403de6..45d610d 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/Type.java +++ b/src/java/com/jogamp/gluegen/cgram/types/Type.java @@ -52,8 +52,8 @@ public abstract class Type implements Cloneable { private String name; private SizeThunk size; - private int cvAttributes; - private int typedefedCVAttributes; + private final int cvAttributes; + private int typedefedCVAttributes; private boolean hasTypedefName; protected Type(String name, SizeThunk size, int cvAttributes) { @@ -75,18 +75,96 @@ public abstract class Type implements Cloneable { /** Returns the name of this type. The returned string is suitable for use as a type specifier. Does not include any const/volatile attributes. */ - public String getName() { return getName(false); } + public final String getName() { return getName(false); } /** Returns the name of this type, optionally including const/volatile attributes. The returned string is suitable for use as a type specifier. */ - public String getName(boolean includeCVAttrs) { + public String getName(boolean includeCVAttrs) { if (!includeCVAttrs) { return name; } return getCVAttributesString() + name; } + private void append(final StringBuilder sb, final String val, final boolean prepComma) { + if( prepComma ) { + sb.append(", "); + } + sb.append(val); + } + // For debugging + public String getDebugString() { + final StringBuilder sb = new StringBuilder(); + boolean prepComma = false; + sb.append("CType["); + if( null != name ) { + append(sb, "'"+name+"'", prepComma); prepComma=true; + } else { + append(sb, "ANON", prepComma); prepComma=true; + } + if( hasTypedefName() ) { + sb.append(" (typedef)"); + } + append(sb, "size ", prepComma); prepComma=true; + if( null != size ) { + final long mdSize; + { + long _mdSize = -1; + try { + _mdSize = size.computeSize(MachineDescription.StaticConfig.X86_64_UNIX.md); + } catch (Exception e) {} + mdSize = _mdSize; + } + sb.append("[fixed ").append(size.hasFixedNativeSize()).append(", lnx64 ").append(mdSize).append("]"); + } else { + sb.append(" ZERO"); + } + append(sb, "[", prepComma); prepComma=false; + if( isConst() ) { + append(sb, "const ", false); + } + if( isVolatile() ) { + append(sb, "volatile ", false); + } + if( isPointer() ) { + append(sb, "pointer*"+pointerDepth(), prepComma); prepComma=true; + } + if( isArray() ) { + append(sb, "array*"+arrayDimension(), prepComma); prepComma=true; + } + if( isBit() ) { + append(sb, "bit", prepComma); prepComma=true; + } + if( isCompound() ) { + sb.append("struct{").append(asCompound().getNumFields()); + append(sb, "}", prepComma); prepComma=true; + } + if( isDouble() ) { + append(sb, "double", prepComma); prepComma=true; + } + if( isEnum() ) { + append(sb, "enum", prepComma); prepComma=true; + } + if( isFloat() ) { + append(sb, "float", prepComma); prepComma=true; + } + if( isFunction() ) { + append(sb, "function", prepComma); prepComma=true; + } + if( isFunctionPointer() ) { + append(sb, "funcPointer", prepComma); prepComma=true; + } + if( isInt() ) { + append(sb, "int", prepComma); prepComma=true; + } + if( isVoid() ) { + append(sb, "void", prepComma); prepComma=true; + } + sb.append("]]"); + return sb.toString(); + } + /** Set the name of this type; used for handling typedefs. */ public void setName(String name) { if (name == null) { @@ -269,6 +347,17 @@ public abstract class Type implements Cloneable { return 1 + arrayType.getElementType().arrayDimension(); } + /** + * Helper method to returns the bottom-most element type of this type. + * <p> + * If this is a multidimensional array or pointer method returns the bottom-most element type, + * otherwise this. + * </p> + */ + public Type getBaseElementType() { + return this; + } + /** Helper routine for list equality comparison */ static <C> boolean listsEqual(List<C> a, List<C> b) { return ((a == null && b == null) || (a != null && b != null && a.equals(b))); 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 3bfb5c4..fd64ba9 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java @@ -36,6 +36,7 @@ import com.jogamp.junit.util.JunitTracer; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.util.Arrays; @@ -978,13 +979,28 @@ public class BaseClass extends JunitTracer { Assert.assertEquals(2, surface.getClipSize()); + TK_Dimension[] allclips = surface.getClips(0, new TK_Dimension[surface.getClipSize()]); + for(int i=0; i<surface.getClipSize(); i++) { - TK_Dimension clip = surface.getClip(i); - Assert.assertEquals(0x44444444 * (i+1) + 0x11111111, clip.getX()); - Assert.assertEquals(0x44444444 * (i+1) + 0x22222222, clip.getY()); - Assert.assertEquals(0x44444444 * (i+1) + 0x33333333, clip.getWidth()); - Assert.assertEquals(0x44444444 * (i+1) + 0x44444444, clip.getHeight()); + TK_Dimension clip0 = surface.getClip(i); + Assert.assertEquals(0x44444444 * (i+1) + 0x11111111, clip0.getX()); + Assert.assertEquals(0x44444444 * (i+1) + 0x22222222, clip0.getY()); + Assert.assertEquals(0x44444444 * (i+1) + 0x33333333, clip0.getWidth()); + Assert.assertEquals(0x44444444 * (i+1) + 0x44444444, clip0.getHeight()); + + TK_Dimension[] clip1 = new TK_Dimension[1]; + surface.getClips(i, clip1); + Assert.assertEquals(0x44444444 * (i+1) + 0x11111111, clip1[0].getX()); + Assert.assertEquals(0x44444444 * (i+1) + 0x22222222, clip1[0].getY()); + Assert.assertEquals(0x44444444 * (i+1) + 0x33333333, clip1[0].getWidth()); + Assert.assertEquals(0x44444444 * (i+1) + 0x44444444, clip1[0].getHeight()); + + Assert.assertEquals(0x44444444 * (i+1) + 0x11111111, allclips[i].getX()); + Assert.assertEquals(0x44444444 * (i+1) + 0x22222222, allclips[i].getY()); + Assert.assertEquals(0x44444444 * (i+1) + 0x33333333, allclips[i].getWidth()); + Assert.assertEquals(0x44444444 * (i+1) + 0x44444444, allclips[i].getHeight()); } + binding.destroySurface(surface); } @@ -1028,10 +1044,10 @@ public class BaseClass extends JunitTracer { } final TK_DimensionPair dimPair = TK_DimensionPair.create(); - dimPair.setPair(sumands); + dimPair.setPair(0, sumands); { sub++; - final TK_Dimension[] dimsGet = dimPair.getPair(); + final TK_Dimension[] dimsGet = dimPair.getPair(0, new TK_Dimension[2]); assertDim("ch11."+sub+": dimsGet[0] ", 11, 22, 33, 44, dimsGet[0]); assertDim("ch11."+sub+": dimsGet[1] ", 1, 2, 3, 4, dimsGet[1]); } @@ -1098,4 +1114,441 @@ public class BaseClass extends JunitTracer { Assert.assertEquals(3, result[0]); } } + + public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d + + /** Test array and pointer bindings of structs */ + public void chapter12TestStructArrayModelConst(Bindingtest1 binding) throws Exception { + final TK_ModelConst model = binding.createModelConst(); + + Assert.assertEquals(3, model.getIntxxPointerCustomLenVal()); + Assert.assertEquals(3, model.getInt32PointerCustomLenVal()); + Assert.assertEquals(3, model.getInt32ArrayFixedLenArrayLength()); + Assert.assertEquals(3, model.getStructArrayFixedLenArrayLength()); + Assert.assertEquals(3, model.getStructPointerCustomLenVal()); + + // field: int32ArrayFixedLen + // CType['int32_t *', size [fixed false, lnx64 12], [array*1]], with array length of 3 + { + final int size = model.getInt32ArrayFixedLenArrayLength(); + final int[] all = model.getInt32ArrayFixedLen(0, new int[size]); + final IntBuffer allB = model.getInt32ArrayFixedLen(); + Assert.assertEquals(size, allB.limit()); + for(int i=0; i<size; i++) { + Assert.assertEquals(21 + i, all[i]); + Assert.assertEquals(21 + i, allB.get(i)); + final int[] s = model.getInt32ArrayFixedLen(i, new int[1]); + Assert.assertEquals(21 + i, s[0]); + } + } + + // field: int32ArrayOneElem + // CType['int32_t *', size [fixed false, lnx64 4], [array*1]], with array length of 1 + { + Assert.assertEquals(30, model.getInt32ArrayOneElem()); + } + + // field: int32PointerCustomLen + // field: CType['int32_t *', size [fixed false, lnx64 8], [pointer*1]], with array length of getInt32PointerCustomLenVal() + { + final int size = model.getInt32PointerCustomLenVal(); + final IntBuffer all = model.getInt32PointerCustomLen(); + Assert.assertEquals(size, all.limit()); + for(int i=0; i<size; i++) { + Assert.assertEquals(31 + i, all.get(i)); + } + } + + // field: int32PointerOneElem + // CType['int32_t *', size [fixed false, lnx64 8], [pointer*1]], with array length of 1 + { + final IntBuffer all = model.getInt32PointerOneElem(); + Assert.assertEquals(1, all.limit()); + Assert.assertEquals(41, all.get(0)); + } + + // field: mat4x4 + // CType['float * *', size [fixed false, lnx64 64], [array*2]], with array length of <code>4*4</code> */ + { + Assert.assertEquals(4*4, model.getMat4x4ArrayLength()); + final FloatBuffer mat4x4 = model.getMat4x4(); + Assert.assertEquals(4*4, mat4x4.limit()); + for(int i=0; i<4; i++) { + final float[] vec4 = model.getMat4x4(i*4, new float[4]); + for(int j=0; j<4; j++) { + Assert.assertEquals(i*4+j, mat4x4.get(i*4+j), EPSILON); + Assert.assertEquals(i*4+j, vec4[j], EPSILON); + } + } + } + + // field: structArrayFixedLen + // field: CType['TK_Dimension *', size [fixed false, lnx64 48], [array*1]], with array length of 3 + { + final int size = model.getStructArrayFixedLenArrayLength(); + final TK_Dimension[] all = model.getStructArrayFixedLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(51 + i * 10, all[i].getX()); + Assert.assertEquals(52 + i * 10, all[i].getY()); + Assert.assertEquals(53 + i * 10, all[i].getWidth()); + Assert.assertEquals(54 + i * 10, all[i].getHeight()); + } + } + + // field: structArrayOneElem + // CType['TK_Dimension *', size [fixed false, lnx64 16], [array*1]], with array length of 1 + { + final TK_Dimension all = model.getStructArrayOneElem(); + Assert.assertEquals(81, all.getX()); + Assert.assertEquals(82, all.getY()); + Assert.assertEquals(83, all.getWidth()); + Assert.assertEquals(84, all.getHeight()); + } + + // field: structPointerCustomLen + // CType['TK_Dimension *', size [fixed false, lnx64 8], [pointer*1]], with array length of getStructPointerCustomLenVal() + { + final int size = model.getStructPointerCustomLenVal(); + final TK_Dimension[] all = model.getStructPointerCustomLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(91 + i * 10, all[i].getX()); + Assert.assertEquals(92 + i * 10, all[i].getY()); + Assert.assertEquals(93 + i * 10, all[i].getWidth()); + Assert.assertEquals(94 + i * 10, all[i].getHeight()); + } + } + + // field: structPointerOneElem + // CType['TK_Dimension *', size [fixed false, lnx64 8], [pointer*1]], with array length of 1 + { + final TK_Dimension all = model.getStructPointerOneElem(); + Assert.assertEquals(121, all.getX()); + Assert.assertEquals(122, all.getY()); + Assert.assertEquals(123, all.getWidth()); + Assert.assertEquals(124, all.getHeight()); + + } + + final long surfaceContext = model.getCtx(); + assertAPTR(0x123456789abcdef0L, surfaceContext); + + model.setCtx(surfaceContext); + assertAPTR(surfaceContext, model.getCtx()); + + { + Assert.assertEquals(12, model.getModelNameArrayFixedLenArrayLength()); + + final ByteBuffer bb = model.getModelNameArrayFixedLen(); + Assert.assertEquals(12, bb.limit()); + + final String exp = "Hello Array"; + final String has = model.getModelNameArrayFixedLenAsString(); + // System.err.println("exp '"+exp+"'"); + System.err.println("has '"+has+"'"); + // dumpStringChars("exp", exp); + dumpStringChars("has", has); + Assert.assertEquals(11, has.length()); // w/o EOS + Assert.assertEquals(exp, has); + } + { + Assert.assertEquals(14, model.getModelNamePointerCStringArrayLength()); + + final ByteBuffer bb = model.getModelNamePointerCString(); + Assert.assertEquals(14, bb.limit()); + + final String exp = "Hello CString"; + final String has = model.getModelNamePointerCStringAsString(); + // System.err.println("exp '"+exp+"'"); + System.err.println("has '"+has+"'"); + // dumpStringChars("exp", exp); + dumpStringChars("has", has); + Assert.assertEquals(13, has.length()); // w/o EOS + Assert.assertEquals(exp, has); + } + { + Assert.assertEquals(14, model.getModelNamePointerCustomLenVal()); + + final ByteBuffer bb = model.getModelNamePointerCustomLen(); + Assert.assertEquals(14, bb.limit()); + + final String exp = "Hello Pointer"; + final String has = model.getModelNamePointerCustomLenAsString(); + // System.err.println("exp '"+exp+"'"); + System.err.println("has '"+has+"'"); + // dumpStringChars("exp", exp); + dumpStringChars("has", has); + Assert.assertEquals(13, has.length()); // w/o EOS + Assert.assertEquals(exp, has); + } + + binding.destroyModelConst(model); + } + private void dumpStringChars(String prefix, String s) { + final int len = s.length(); + for(int i=0; i<len; i++) { + final char c = s.charAt(i); + System.err.printf("%s %3d: 0x%X %c%n", prefix, i, (int)c, c); + } + } + + public void chapter13TestStructArrayModelMutable(Bindingtest1 binding) throws Exception { + final TK_ModelMutable model = binding.createModelMutable(); + + Assert.assertEquals(3, model.getIntxxPointerCustomLenVal()); + Assert.assertEquals(3, model.getInt32PointerCustomLenVal()); + Assert.assertEquals(3, model.getInt32ArrayFixedLenArrayLength()); + Assert.assertEquals(3, model.getStructArrayFixedLenArrayLength()); + Assert.assertEquals(3, model.getStructPointerCustomLenVal()); + + // field: int32ArrayFixedLen + // CType['int32_t *', size [fixed false, lnx64 12], [array*1]], with array length of 3 + { + final int size = model.getInt32ArrayFixedLenArrayLength(); + { + final int[] values = new int[] { 1, 2, 3 }; + model.setInt32ArrayFixedLen(0, values); + + final int[] all = model.getInt32ArrayFixedLen(0, new int[size]); + final IntBuffer allB = model.getInt32ArrayFixedLen(); + Assert.assertEquals(size, allB.limit()); + for(int i=0; i<size; i++) { + Assert.assertEquals(1 + i, all[i]); + Assert.assertEquals(1 + i, allB.get(i)); + final int[] s = model.getInt32ArrayFixedLen(i, new int[1]); + Assert.assertEquals(1 + i, s[0]); + } + } + { + for(int i=0; i<size; i++) { + final int[] ia = new int[] { 4 + i }; + model.setInt32ArrayFixedLen(i, ia); + } + + final int[] all = model.getInt32ArrayFixedLen(0, new int[size]); + final IntBuffer allB = model.getInt32ArrayFixedLen(); + Assert.assertEquals(size, allB.limit()); + for(int i=0; i<size; i++) { + Assert.assertEquals(4 + i, all[i]); + Assert.assertEquals(4 + i, allB.get(i)); + final int[] s = model.getInt32ArrayFixedLen(i, new int[1]); + Assert.assertEquals(4 + i, s[0]); + } + } + } + + // field: int32ArrayOneElem + // CType['int32_t *', size [fixed false, lnx64 4], [array*1]], with array length of 1 + { + model.setInt32ArrayOneElem(1); + Assert.assertEquals(1, model.getInt32ArrayOneElem()); + } + + // field: int32PointerCustomLen + // field: CType['int32_t *', size [fixed false, lnx64 8], [pointer*1]], with array length of getInt32PointerCustomLenVal() + { + final int size = model.getInt32PointerCustomLenVal(); + { + final IntBuffer all0 = model.getInt32PointerCustomLen(); + Assert.assertEquals(size, all0.limit()); + for(int i=0; i<size; i++) { + all0.put(i, 1+i); + } + + final IntBuffer all1 = model.getInt32PointerCustomLen(); + Assert.assertEquals(size, all1.limit()); + for(int i=0; i<size; i++) { + Assert.assertEquals(1 + i, all1.get(i)); + } + } + } + + // field: int32PointerOneElem + // CType['int32_t *', size [fixed false, lnx64 8], [pointer*1]], with array length of 1 + { + { + final IntBuffer one0 = model.getInt32PointerOneElem(); + Assert.assertEquals(1, one0.limit()); + one0.put(0, 1); + + final IntBuffer one1 = model.getInt32PointerOneElem(); + Assert.assertEquals(1, one1.limit()); + Assert.assertEquals(1, one1.get(0)); + } + } + + + // field: mat4x4 + // CType['float * *', size [fixed false, lnx64 64], [array*2]], with array length of <code>4*4</code> */ + { + model.setMat4x4(0*4, new float[] { 11, 12, 13, 14 } ); + model.setMat4x4(1*4, new float[] { 21, 22, 23, 24 } ); + model.setMat4x4(2*4, new float[] { 31, 32, 33, 34 } ); + model.setMat4x4(3*4, new float[] { 41, 42, 43, 44 } ); + + Assert.assertEquals(4*4, model.getMat4x4ArrayLength()); + final FloatBuffer mat4x4 = model.getMat4x4(); + Assert.assertEquals(4*4, mat4x4.limit()); + for(int i=0; i<4; i++) { + final float[] vec4 = model.getMat4x4(i*4, new float[4]); + for(int j=0; j<4; j++) { + Assert.assertEquals((i+1)*10+(j+1), mat4x4.get(i*4+j), EPSILON); + Assert.assertEquals((i+1)*10+(j+1), vec4[j], EPSILON); + } + } + } + + // field: structArrayFixedLen + // field: CType['TK_Dimension *', size [fixed false, lnx64 48], [array*1]], with array length of 3 + { + final int size = model.getStructArrayFixedLenArrayLength(); + { + for(int i=0; i<size; i++) { + final TK_Dimension d = TK_Dimension.create(); + d.setX(1+i*10); + d.setY(2+i*10); + d.setWidth(3+i*10); + d.setHeight(4+i*10); + model.setStructArrayFixedLen(i, d); + } + final TK_Dimension[] all = model.getStructArrayFixedLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(1 + i * 10, all[i].getX()); + Assert.assertEquals(2 + i * 10, all[i].getY()); + Assert.assertEquals(3 + i * 10, all[i].getWidth()); + Assert.assertEquals(4 + i * 10, all[i].getHeight()); + final TK_Dimension[] one = model.getStructArrayFixedLen(i, new TK_Dimension[1]); + Assert.assertEquals(1 + i * 10, one[0].getX()); + Assert.assertEquals(2 + i * 10, one[0].getY()); + Assert.assertEquals(3 + i * 10, one[0].getWidth()); + Assert.assertEquals(4 + i * 10, one[0].getHeight()); + } + } + { + final TK_Dimension[] da = new TK_Dimension[size]; + for(int i=0; i<size; i++) { + final TK_Dimension d = TK_Dimension.create(); + d.setX(5+i*10); + d.setY(6+i*10); + d.setWidth(7+i*10); + d.setHeight(8+i*10); + da[i] = d; + } + model.setStructArrayFixedLen(0, da); + + final TK_Dimension[] all = model.getStructArrayFixedLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(5 + i * 10, all[i].getX()); + Assert.assertEquals(6 + i * 10, all[i].getY()); + Assert.assertEquals(7 + i * 10, all[i].getWidth()); + Assert.assertEquals(8 + i * 10, all[i].getHeight()); + final TK_Dimension[] one = model.getStructArrayFixedLen(i, new TK_Dimension[1]); + Assert.assertEquals(5 + i * 10, one[0].getX()); + Assert.assertEquals(6 + i * 10, one[0].getY()); + Assert.assertEquals(7 + i * 10, one[0].getWidth()); + Assert.assertEquals(8 + i * 10, one[0].getHeight()); + } + } + { + for(int i=0; i<size; i++) { + final TK_Dimension d = TK_Dimension.create(); + d.setX(1+i*10); + d.setY(3+i*10); + d.setWidth(5+i*10); + d.setHeight(7+i*10); + model.setStructArrayFixedLen(i, new TK_Dimension[] { d }); + } + + final TK_Dimension[] all = model.getStructArrayFixedLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(1 + i * 10, all[i].getX()); + Assert.assertEquals(3 + i * 10, all[i].getY()); + Assert.assertEquals(5 + i * 10, all[i].getWidth()); + Assert.assertEquals(7 + i * 10, all[i].getHeight()); + final TK_Dimension[] one = model.getStructArrayFixedLen(i, new TK_Dimension[1]); + Assert.assertEquals(1 + i * 10, one[0].getX()); + Assert.assertEquals(3 + i * 10, one[0].getY()); + Assert.assertEquals(5 + i * 10, one[0].getWidth()); + Assert.assertEquals(7 + i * 10, one[0].getHeight()); + } + } + } + + // field: structArrayOneElem + // CType['TK_Dimension *', size [fixed false, lnx64 16], [array*1]], with array length of 1 + { + { + final TK_Dimension d = TK_Dimension.create(); + d.setX(1); + d.setY(2); + d.setWidth(3); + d.setHeight(4); + model.setStructArrayOneElem(d); + } + { + final TK_Dimension one = model.getStructArrayOneElem(); + Assert.assertEquals(1, one.getX()); + Assert.assertEquals(2, one.getY()); + Assert.assertEquals(3, one.getWidth()); + Assert.assertEquals(4, one.getHeight()); + } + } + + // field: structPointerCustomLen + // CType['TK_Dimension *', size [fixed false, lnx64 8], [pointer*1]], with array length of getStructPointerCustomLenVal() + { + final int size = model.getStructPointerCustomLenVal(); + { + final TK_Dimension[] all = model.getStructPointerCustomLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + final TK_Dimension d = all[i]; + d.setX(1+i*10); + d.setY(2+i*10); + d.setWidth(3+i*10); + d.setHeight(4+i*10); + } + } + { + final TK_Dimension[] all = model.getStructPointerCustomLen(0, new TK_Dimension[size]); + for(int i=0; i<size; i++) { + Assert.assertEquals(1 + i * 10, all[i].getX()); + Assert.assertEquals(2 + i * 10, all[i].getY()); + Assert.assertEquals(3 + i * 10, all[i].getWidth()); + Assert.assertEquals(4 + i * 10, all[i].getHeight()); + final TK_Dimension[] one = model.getStructPointerCustomLen(i, new TK_Dimension[1]); + Assert.assertEquals(1 + i * 10, one[0].getX()); + Assert.assertEquals(2 + i * 10, one[0].getY()); + Assert.assertEquals(3 + i * 10, one[0].getWidth()); + Assert.assertEquals(4 + i * 10, one[0].getHeight()); + } + } + } + + // field: structPointerOneElem + // CType['TK_Dimension *', size [fixed false, lnx64 8], [pointer*1]], with array length of 1 + { + { + final TK_Dimension d = model.getStructPointerOneElem(); + d.setX(1); + d.setY(2); + d.setWidth(3); + d.setHeight(4); + } + { + final TK_Dimension one = model.getStructPointerOneElem(); + Assert.assertEquals(1, one.getX()); + Assert.assertEquals(2, one.getY()); + Assert.assertEquals(3, one.getWidth()); + Assert.assertEquals(4, one.getHeight()); + } + + } + + final long surfaceContext = model.getCtx(); + assertAPTR(0x123456789abcdef0L, surfaceContext); + + model.setCtx(surfaceContext); + assertAPTR(surfaceContext, model.getCtx()); + + binding.destroyModelMutable(model); + } } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java index e63f255..e3e3ca9 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java @@ -132,6 +132,22 @@ public class Test1p1JavaEmitter extends BaseClass { chapter11TestCompoundCallByValue(new Bindingtest1p1Impl()); } + /** + * Test compound access read-only + */ + @Test + public void chapter12TestStructArrayModelConst() throws Exception { + chapter12TestStructArrayModelConst(new Bindingtest1p1Impl()); + } + + /** + * Test compound access read-write + */ + @Test + public void chapter13TestStructArrayModelMutable() throws Exception { + chapter13TestStructArrayModelMutable(new Bindingtest1p1Impl()); + } + public static void main(String args[]) throws IOException { String tstname = Test1p1JavaEmitter.class.getName(); org.junit.runner.JUnitCore.main(tstname); diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java index 07201c0..39e3948 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java @@ -30,7 +30,6 @@ package com.jogamp.gluegen.test.junit.generation; import java.io.IOException; -import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest1p1Impl; import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest1p2Impl; import com.jogamp.common.os.NativeLibrary; @@ -142,6 +141,22 @@ public class Test1p2ProcAddressEmitter extends BaseClass { } /** + * Test compound access read-only + */ + @Test + public void chapter12TestStructArrayModelConst() throws Exception { + chapter12TestStructArrayModelConst(new Bindingtest1p2Impl()); + } + + /** + * Test compound access read-write + */ + @Test + public void chapter13TestStructArrayModelMutable() throws Exception { + chapter13TestStructArrayModelMutable(new Bindingtest1p2Impl()); + } + + /** * Verifies unloading of the new library. */ @AfterClass diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg index d4e32cc..eca133e 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg @@ -41,8 +41,12 @@ EmitStruct TK_Dimension StructPackage TK_DimensionPair com.jogamp.gluegen.test.junit.generation EmitStruct TK_DimensionPair +EmitStruct TK_Surface StructPackage TK_Surface com.jogamp.gluegen.test.junit.generation EmitStruct TK_Surface +ReturnedArrayLength TK_Surface.clips getClipSize() +IgnoreField TK_Surface GetComponent + # Implements TK_Surface TḴ_??? StructPackage TK_ComplicatedSuperSet com.jogamp.gluegen.test.junit.generation @@ -50,10 +54,44 @@ EmitStruct TK_ComplicatedSuperSet # Implements TK_ComplicatedSuperSet TḴ_??? ReturnValueCapacity createSurface sizeof(TK_Surface) -ReturnValueCapacity getClip sizeof(TK_Dimension) +ReturnValueCapacity TK_Surface.getClip sizeof(TK_Dimension) ReturnValueCapacity createComplicatedSuperSet sizeof(TK_ComplicatedSuperSet) +EmitStruct TK_ModelConst +StructPackage TK_ModelConst com.jogamp.gluegen.test.junit.generation +ReturnedArrayLength TK_ModelConst.intxxArrayCustomLen getIntxxArrayCustomLenVal() +ReturnedArrayLength TK_ModelConst.intxxPointerCustomLen getIntxxPointerCustomLenVal() +ReturnedArrayLength TK_ModelConst.int32ArrayCustomLen getInt32ArrayCustomLenVal() +ReturnedArrayLength TK_ModelConst.int32PointerCustomLen getInt32PointerCustomLenVal() +ReturnedArrayLength TK_ModelConst.structArrayCustomLen getStructArrayCustomLenVal() +ReturnedArrayLength TK_ModelConst.structPointerCustomLen getStructPointerCustomLenVal() +ReturnedArrayLength TK_ModelConst.int32PointerOneElem 1 +ReturnValueCapacity TK_ModelConst.int32PointerOneElem 1 * sizeof(int32_t) /* overridden by ReturnValueCapacity */ +ReturnedArrayLength TK_ModelConst.structPointerOneElem 1 +ReturnsString TK_ModelConst.modelNameArrayFixedLen +ReturnsString TK_ModelConst.modelNamePointerCString +ReturnsString TK_ModelConst.modelNamePointerCustomLen +ReturnedArrayLength TK_ModelConst.modelNamePointerCustomLen getModelNamePointerCustomLenVal() + +EmitStruct TK_ModelMutable +StructPackage TK_ModelMutable com.jogamp.gluegen.test.junit.generation +ReturnedArrayLength TK_ModelMutable.intxxArrayCustomLen getIntxxArrayCustomLenVal() +ReturnedArrayLength TK_ModelMutable.intxxPointerCustomLen getIntxxPointerCustomLenVal() +ReturnedArrayLength TK_ModelMutable.int32ArrayCustomLen getInt32ArrayCustomLenVal() +ReturnedArrayLength TK_ModelMutable.int32PointerCustomLen getInt32PointerCustomLenVal() +ReturnedArrayLength TK_ModelMutable.structArrayCustomLen getStructArrayCustomLenVal() +ReturnedArrayLength TK_ModelMutable.structPointerCustomLen getStructPointerCustomLenVal() +ReturnedArrayLength TK_ModelMutable.int32PointerOneElem 1 +ReturnedArrayLength TK_ModelMutable.structPointerOneElem 1 +ReturnsString TK_ModelMutable.modelNameArrayFixedLen +ReturnsString TK_ModelMutable.modelNamePointerCString +ReturnsString TK_ModelMutable.modelNamePointerCustomLen +ReturnedArrayLength TK_ModelMutable.modelNamePointerCustomLen getModelNamePointerCustomLenVal() + +ReturnValueCapacity createModelConst sizeof(TK_ModelConst) +ReturnValueCapacity createModelMutable sizeof(TK_ModelMutable) + # Imports needed by all glue code Import java.nio.* Import java.util.* @@ -65,6 +103,8 @@ Import com.jogamp.gluegen.test.junit.generation.TK_DimensionPair Import com.jogamp.gluegen.test.junit.generation.TK_Engine Import com.jogamp.gluegen.test.junit.generation.TK_ComplicatedSuperSet Import com.jogamp.gluegen.test.junit.generation.TK_ComplicatedSubSet +Import com.jogamp.gluegen.test.junit.generation.TK_ModelConst +Import com.jogamp.gluegen.test.junit.generation.TK_ModelMutable 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 3dc1ac5..9999274 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c @@ -372,6 +372,7 @@ MYAPI TK_Surface * MYAPIENTRY createSurface() { MYAPI void MYAPIENTRY destroySurface(TK_Surface * surface) { assert(NULL!=surface); + assert(NULL!=surface->clips); free(surface->clips); // free(surface->engine); free(surface); @@ -578,3 +579,112 @@ MYAPI void MYAPIENTRY addByte(const char summands[2], char result[1]) { result[0] = summands[0] + summands[1]; } +MYAPI TK_ModelMutable * MYAPIENTRY createModelMutable() { + int i, j; + TK_ModelMutable * s = calloc(1, sizeof(TK_ModelMutable)); + + s->intxxArrayFixedLen[0]=1; + s->intxxArrayFixedLen[1]=2; + s->intxxArrayFixedLen[2]=3; + + s->intxxPointerCustomLen = calloc(3, sizeof(int)); + s->intxxPointerCustomLen[0] = 11; + s->intxxPointerCustomLen[1] = 12; + s->intxxPointerCustomLen[2] = 13; + s->intxxPointerCustomLenVal=3; + + s->int32ArrayFixedLen[0] = 21; + s->int32ArrayFixedLen[1] = 22; + s->int32ArrayFixedLen[2] = 23; + + s->int32ArrayOneElem[0] = 30; + + s->int32PointerCustomLen = calloc(3, sizeof(int)); + s->int32PointerCustomLen[0] = 31; + s->int32PointerCustomLen[1] = 32; + s->int32PointerCustomLen[2] = 33; + s->int32PointerCustomLenVal=3; + + s->int32PointerOneElem = calloc(1, sizeof(int)); + s->int32PointerOneElem[0] = 41; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + s->mat4x4[i][j] = i*4 + j; + } + } + + s->structArrayFixedLen[0].x = 51; + s->structArrayFixedLen[0].y = 52; + s->structArrayFixedLen[0].width = 53; + s->structArrayFixedLen[0].height = 54; + s->structArrayFixedLen[1].x = 61; + s->structArrayFixedLen[1].y = 62; + s->structArrayFixedLen[1].width = 63; + s->structArrayFixedLen[1].height = 64; + s->structArrayFixedLen[2].x = 71; + s->structArrayFixedLen[2].y = 72; + s->structArrayFixedLen[2].width = 73; + s->structArrayFixedLen[2].height = 74; + + s->structArrayOneElem[0].x = 81; + s->structArrayOneElem[0].y = 82; + s->structArrayOneElem[0].width = 83; + s->structArrayOneElem[0].height = 84; + + s->structPointerCustomLen = (TK_Dimension *) calloc(3, sizeof(TK_Dimension)); + s->structPointerCustomLen[0].x = 91; + s->structPointerCustomLen[0].y = 92; + s->structPointerCustomLen[0].width = 93; + s->structPointerCustomLen[0].height = 94; + s->structPointerCustomLen[1].x = 101; + s->structPointerCustomLen[1].y = 102; + s->structPointerCustomLen[1].width = 103; + s->structPointerCustomLen[1].height = 104; + s->structPointerCustomLen[2].x = 111; + s->structPointerCustomLen[2].y = 112; + s->structPointerCustomLen[2].width = 113; + s->structPointerCustomLen[2].height = 114; + s->structPointerCustomLenVal = 3; + + s->structPointerOneElem = (TK_Dimension *) calloc(1, sizeof(TK_Dimension)); + s->structPointerOneElem[0].x = 121; + s->structPointerOneElem[0].y = 122; + s->structPointerOneElem[0].width = 123; + s->structPointerOneElem[0].height = 124; + + s->ctx = (void *) 0x123456789abcdef0UL; + + strncpy(s->modelNameArrayFixedLen, "Hello Array", sizeof(s->modelNameArrayFixedLen)); + + s->modelNamePointerCString = calloc(13+1, sizeof(char)); + strncpy(s->modelNamePointerCString, "Hello CString", 13+1); + + s->modelNamePointerCustomLen = calloc(13+1, sizeof(char)); + strncpy(s->modelNamePointerCustomLen, "Hello Pointer", 13+1); + s->modelNamePointerCustomLenVal = 13+1; + + return s; +} + +MYAPI void MYAPIENTRY destroyModelMutable(TK_ModelMutable * s) { + assert(NULL!=s); + assert(NULL!=s->intxxPointerCustomLen); + assert(NULL!=s->int32PointerCustomLen); + assert(NULL!=s->int32PointerOneElem); + assert(NULL!=s->structPointerCustomLen); + free(s->intxxPointerCustomLen); + free(s->int32PointerCustomLen); + free(s->int32PointerOneElem); + free(s->structPointerCustomLen); + free(s->modelNamePointerCString); + free(s->modelNamePointerCustomLen); + free(s); +} + +MYAPI TK_ModelConst * MYAPIENTRY createModelConst() { + return (TK_ModelConst *)createModelMutable(); +} +MYAPI void MYAPIENTRY destroyModelConst(TK_ModelConst * s) { + destroyModelMutable((TK_ModelMutable *)s); +} 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 7343172..ebb41d3 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h @@ -183,15 +183,23 @@ typedef struct { TK_Context ctx; } TK_ContextWrapper; +struct _jobject; +typedef struct _jobject *jobject; +struct JNINativeInterface_; +typedef const struct JNINativeInterface_ *JNIEnv; + + typedef struct tk_Surface { TK_Context ctx; TK_ContextWrapper ctxWrapper; - // const TK_Engine * engine; TK_Engine engine; TK_Dimension bounds; int32_t clipSize; TK_Dimension * clips; TK_Dimension * (MYAPIENTRY *getClip) (struct tk_Surface * ds, int idx); + + jobject (MYAPIENTRY *GetComponent)(JNIEnv* env, void* platformInfo); + } TK_Surface; typedef struct { @@ -274,3 +282,71 @@ MYAPI void MYAPIENTRY intToRgba(int irgba, char rgbaSink[4]); MYAPI void MYAPIENTRY addInt(const int summands[2], int result[1]); MYAPI void MYAPIENTRY addByte(const char summands[2], char result[1]); +typedef struct { + const int intxxArrayFixedLen[3]; + + const int * intxxPointerCustomLen; + const int intxxPointerCustomLenVal; + + const int32_t int32ArrayFixedLen[3]; + const int32_t int32ArrayOneElem[1]; + + const int32_t * int32PointerCustomLen; + const int32_t int32PointerCustomLenVal; + + const int32_t * int32PointerOneElem; + + const float mat4x4[4][4]; + + const TK_Dimension structArrayFixedLen[3]; + const TK_Dimension structArrayOneElem[1]; + + const TK_Dimension * structPointerCustomLen; + const int32_t structPointerCustomLenVal; + const TK_Dimension * structPointerOneElem; + + const TK_Context ctx; + + const char modelNameArrayFixedLen[12]; /* 'Hello Array' len=11+1 */ + const char * modelNamePointerCString; /* 'Hello CString' len=13+1 */ + const char * modelNamePointerCustomLen; /* 'Hello Pointer' len=13+1 */ + const int modelNamePointerCustomLenVal; /* 13+1 */ + +} TK_ModelConst; + +typedef struct { + int intxxArrayFixedLen[3]; + + int * intxxPointerCustomLen; + int intxxPointerCustomLenVal; + + int32_t int32ArrayFixedLen[3]; + int32_t int32ArrayOneElem[1]; + + int32_t * int32PointerCustomLen; + int32_t int32PointerCustomLenVal; + + int32_t * int32PointerOneElem; + + float mat4x4[4][4]; + + TK_Dimension structArrayFixedLen[3]; + TK_Dimension structArrayOneElem[1]; + + TK_Dimension * structPointerCustomLen; + int32_t structPointerCustomLenVal; + TK_Dimension * structPointerOneElem; + + TK_Context ctx; + + char modelNameArrayFixedLen[12]; /* 'Hello Array' len=11+1 */ + const char * modelNamePointerCString; /* 'Hello CString' len=13+1 */ + char * modelNamePointerCustomLen; /* 'Hello Pointer' len=13+1 */ + int modelNamePointerCustomLenVal; /* 13+1 */ + +} TK_ModelMutable; + +MYAPI TK_ModelConst * MYAPIENTRY createModelConst(); +MYAPI void MYAPIENTRY destroyModelConst(TK_ModelConst * s); +MYAPI TK_ModelMutable * MYAPIENTRY createModelMutable(); +MYAPI void MYAPIENTRY destroyModelMutable(TK_ModelMutable * s); |