summaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/gluegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/jogamp/gluegen')
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java37
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java74
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java1158
-rw-r--r--src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java64
-rw-r--r--src/java/com/jogamp/gluegen/JavaType.java70
-rw-r--r--src/java/com/jogamp/gluegen/MethodBinding.java12
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/ArrayType.java7
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/FunctionType.java20
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/PointerType.java12
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/StructLayout.java12
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/Type.java97
11 files changed, 1149 insertions, 414 deletions
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)));