aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-06-29 02:35:01 +0200
committerSven Gothel <[email protected]>2023-06-29 02:35:01 +0200
commit809a7f84fcada7fbde8b7d0c226b78492fbfc616 (patch)
treee73d0bbe23736bfcf3180dfd3c0eb0f1742aa6e8 /src
parenta1b107dd3fbe2070a1e667d8d7702912b0af7071 (diff)
GlueGen CMethodBindingEmitter: Refactor emitBodyReturnResult() -> emitBodyMapCToJNIType(): Reuse to converting any C-type argument to java JNI type (i.e. native callback to JavaCallback)
Diffstat (limited to 'src')
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java246
1 files changed, 148 insertions, 98 deletions
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index 66d4814..d0e0c45 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -399,7 +399,9 @@ public class CMethodBindingEmitter extends FunctionEmitter {
emitBodyCallCFunction();
emitBodyUserVariableAssignments();
emitBodyVariablePostCallCleanup();
- emitBodyReturnResult();
+ if( emitBodyMapCToJNIType(-1 /* return value */, true /* addLocalVar */) ) {
+ unit.emitln(" return _res_jni;");
+ }
unit.emitln("}");
unit.emitln();
}
@@ -1005,128 +1007,176 @@ public class CMethodBindingEmitter extends FunctionEmitter {
}
}
- protected void emitBodyReturnResult()
+ /**
+ * Emit code, converting a C type into a java JNI-type.
+ * <p>
+ * The resulting JNI value is assigned to a local JNI variable named cArgName+"_jni"
+ * with `cArgName = binding.getArgumentName(argIdx)` or `cArgName = "_res"`.
+ * </p>
+ * @param argIdx -1 is return value, [0..n] is argument index
+ * @param addLocalVar if true, emit instantiating the local JNI variable.
+ * @return true if a non-void result has been produced, otherwise false
+ */
+ protected boolean emitBodyMapCToJNIType(final int argIdx, final boolean addLocalVar)
{
// WARNING: this code assumes that the return type has already been
// typedef-resolved.
- final Type cReturnType = binding.getCReturnType();
+ final boolean isReturnVal;
+ final Type cType;
+ final JavaType javaType;
+ final String cArgName;
+ if( 0 > argIdx ) {
+ isReturnVal = true;
+ cType = binding.getCReturnType();
+ javaType = binding.getJavaReturnType();
+ cArgName = "_res";
+ } else {
+ isReturnVal = false;
+ cType = binding.getCArgumentType(argIdx);
+ javaType = binding.getJavaArgumentType(argIdx);
+ cArgName = binding.getArgumentName(argIdx);
+ }
+ final String javaArgName = cArgName + "_jni";
- // Return result if necessary
- if (!cReturnType.isVoid()) {
- final JavaType javaReturnType = binding.getJavaReturnType();
- if (javaReturnType.isPrimitive()) {
- unit.emit(" return ");
- if (cReturnType.isPointer()) {
- // Pointer being converted to int or long: cast this result
- // (through intptr_t to avoid compiler warnings with gcc)
- unit.emit("(" + javaReturnType.jniTypeName() + ") (intptr_t) ");
+ if ( cType.isVoid() ) {
+ // No result to produce
+ return false;
+ }
+ if (javaType.isPrimitive()) {
+ if( addLocalVar ) {
+ unit.emit(" "+javaType.jniTypeName()+" "+javaArgName+" = ");
+ } else {
+ unit.emit(" "+javaArgName+" = ");
+ }
+ if (cType.isPointer()) {
+ // Pointer being converted to int or long: cast this result
+ // (through intptr_t to avoid compiler warnings with gcc)
+ unit.emit("(" + javaType.jniTypeName() + ") (intptr_t) ");
+ }
+ unit.emit(cArgName);
+ unit.emitln(";");
+ } else if ( !cType.isPointer() && javaType.isCompoundTypeWrapper() ) { // isReturnCompoundByValue()
+ if( addLocalVar ) {
+ unit.emit(" "+javaType.jniTypeName()+" "+javaArgName+" = ");
+ } else {
+ unit.emit(" "+javaArgName+" = ");
}
- unit.emitln("_res;");
- } else if ( !cReturnType.isPointer() && javaReturnType.isCompoundTypeWrapper() ) { // isReturnCompoundByValue()
final String returnSizeOf;
- if (returnValueCapacityExpression != null) {
+ if ( isReturnVal && returnValueCapacityExpression != null ) {
returnSizeOf = returnValueCapacityExpression.format(argumentNameArray());
} else {
- returnSizeOf = "sizeof(" + cReturnType.getCName() + ")";
+ returnSizeOf = "sizeof(" + cType.getCName() + ")";
}
- unit.emitln(" return JVMUtil_NewDirectByteBufferCopy(env, _clazzBuffers, &_res, "+returnSizeOf+");");
+ unit.emitln("JVMUtil_NewDirectByteBufferCopy(env, _clazzBuffers, &"+cArgName+", "+returnSizeOf+");");
unit.addTailCode(CCodeUnit.NewDirectByteBufferCopyUnitCode);
- } else if (javaReturnType.isNIOBuffer() || javaReturnType.isCompoundTypeWrapper()) {
- unit.emitln(" if (NULL == _res) return NULL;");
- unit.emit(" return (*env)->NewDirectByteBuffer(env, (void *)_res, ");
+ } else if (javaType.isNIOBuffer() || javaType.isCompoundTypeWrapper()) {
+ if( addLocalVar ) {
+ unit.emit(" "+javaType.jniTypeName()+" "+javaArgName+" = ");
+ } else {
+ unit.emit(" "+javaArgName+" = ");
+ }
+ unit.emit("(NULL == "+cArgName+") ? NULL : (*env)->NewDirectByteBuffer(env, (void *)"+cArgName+", ");
// See whether capacity has been specified
- if (returnValueCapacityExpression != null) {
- unit.emitln( returnValueCapacityExpression.format( argumentNameArray() ) + ");");
+ if ( isReturnVal && returnValueCapacityExpression != null) {
+ unit.emitln( returnValueCapacityExpression.format( argumentNameArray() ) + ");");
} else {
- final Type cReturnTargetType = cReturnType.isPointer() ? cReturnType.getTargetType() : null;
- int mode = 0;
- if ( 1 == cReturnType.pointerDepth() && null != cReturnTargetType ) {
- if( cReturnTargetType.isCompound() ) {
- if( !cReturnTargetType.isAnon() &&
- cReturnTargetType.asCompound().getNumFields() > 0 )
- {
- // fully declared non-anonymous struct pointer: pass content
- if ( cReturnTargetType.getSize() == null ) {
- throw new GlueGenException(
- "Error emitting code for compound return type "+
- "for function \"" + binding + "\": " +
- "Structs to be emitted should have been laid out by this point " +
- "(type " + cReturnTargetType.getCName() + " / " +
- cReturnTargetType.getDebugString() + " was not) for "+binding.getCSymbol(),
- binding.getCSymbol().getASTLocusTag()
- );
+ final Type cTargetType = cType.isPointer() ? cType.getTargetType() : null;
+ int mode = 0;
+ if ( 1 == cType.pointerDepth() && null != cTargetType ) {
+ if( cTargetType.isCompound() ) {
+ if( !cTargetType.isAnon() &&
+ cTargetType.asCompound().getNumFields() > 0 )
+ {
+ // fully declared non-anonymous struct pointer: pass content
+ if ( cTargetType.getSize() == null ) {
+ throw new GlueGenException(
+ "Error emitting code for compound type "+
+ "for function \"" + binding + "\": " +
+ "Structs to be emitted should have been laid out by this point " +
+ "(type " + cTargetType.getCName() + " / " +
+ cTargetType.getDebugString() + " was not) for "+binding.getCSymbol(),
+ binding.getCSymbol().getASTLocusTag() );
+ }
+ unit.emitln("sizeof(" + cTargetType.getCName() + ") );");
+ mode = 10;
+ } else if( cTargetType.asCompound().getNumFields() == 0 ) {
+ // anonymous struct pointer: pass pointer
+ unit.emitln("sizeof(" + cType.getCName() + ") );");
+ mode = 11;
+ }
+ }
+ if( 0 == mode ) {
+ if( cTargetType.isPrimitive() ) {
+ // primitive pointer: pass primitive
+ unit.emitln("sizeof(" + cTargetType.getCName() + ") );");
+ mode = 20;
+ } else if( cTargetType.isVoid() ) {
+ // void pointer: pass pointer
+ unit.emitln("sizeof(" + cType.getCName() + ") );");
+ mode = 21;
}
- unit.emitln("sizeof(" + cReturnTargetType.getCName() + ") );");
- mode = 10;
- } else if( cReturnTargetType.asCompound().getNumFields() == 0 ) {
- // anonymous struct pointer: pass pointer
- unit.emitln("sizeof(" + cReturnType.getCName() + ") );");
- mode = 11;
}
}
if( 0 == mode ) {
- if( cReturnTargetType.isPrimitive() ) {
- // primitive pointer: pass primitive
- unit.emitln("sizeof(" + cReturnTargetType.getCName() + ") );");
- mode = 20;
- } else if( cReturnTargetType.isVoid() ) {
- // void pointer: pass pointer
- unit.emitln("sizeof(" + cReturnType.getCName() + ") );");
- mode = 21;
+ if( null != cfg.typeInfo(cType) ) { // javaReturnType.isOpaqued() covered above via isPrimitive()
+ // Opaque
+ unit.emitln("sizeof(" + cType.getCName() + ") );");
+ mode = 88;
+ } else {
+ final String wmsg = "Assumed return size of equivalent C return type";
+ unit.emitln("sizeof(" + cType.getCName() + ") ); // WARNING: "+wmsg);
+ mode = 99;
+ LOG.warning(binding.getCSymbol().getASTLocusTag(),
+ "No capacity specified for java.nio.Buffer return " +
+ "value for function \"" + binding.getName() + "\". " + wmsg + " (sizeof(" + cType.getCName() + ")): " + binding);
}
}
- }
- if( 0 == mode ) {
- if( null != cfg.typeInfo(cReturnType) ) { // javaReturnType.isOpaqued() covered above via isPrimitive()
- // Opaque
- unit.emitln("sizeof(" + cReturnType.getCName() + ") );");
- mode = 88;
- } else {
- final String wmsg = "Assumed return size of equivalent C return type";
- unit.emitln("sizeof(" + cReturnType.getCName() + ") ); // WARNING: "+wmsg);
- mode = 99;
- LOG.warning(binding.getCSymbol().getASTLocusTag(),
- "No capacity specified for java.nio.Buffer return " +
- "value for function \"" + binding.getName() + "\". " + wmsg + " (sizeof(" + cReturnType.getCName() + ")): " + binding);
- }
- }
- unit.emitln(" /** ");
- unit.emitln(" * mode: "+mode);
- unit.emitln(" * cReturnType: "+cReturnType.getDebugString());
- unit.emitln(" * cReturnTargetType: "+cReturnTargetType.getDebugString());
- unit.emitln(" * javaReturnType: "+javaReturnType.getDebugString());
- unit.emitln(" */");
+ unit.emitln(" /** ");
+ unit.emitln(" * mode: "+mode+", arg #"+argIdx);
+ unit.emitln(" * cType: "+cType.getDebugString());
+ unit.emitln(" * cTargetType: "+cTargetType.getDebugString());
+ unit.emitln(" * javaType: "+javaType.getDebugString());
+ unit.emitln(" */");
+ }
+ } else if (javaType.isString()) {
+ if( addLocalVar ) {
+ unit.emit(" "+javaType.jniTypeName()+" "+javaArgName+" = ");
+ } else {
+ unit.emit(" "+javaArgName+" = ");
}
- } else if (javaReturnType.isString()) {
- unit.emitln(" if (NULL == _res) return NULL;");
- unit.emitln(" return (*env)->NewStringUTF(env, (const char *)_res);");
- } else if (javaReturnType.isArrayOfCompoundTypeWrappers() ||
- (javaReturnType.isArray() && javaReturnType.isNIOByteBufferArray())) {
- unit.emitln(" if (NULL == _res) return NULL;");
- if (returnValueLengthExpression == null) {
- throw new GlueGenException("Error while generating C code: no length specified for array returned from function " +
- binding, binding.getCSymbol().getASTLocusTag());
+ unit.emitln("(NULL == "+cArgName+") ? NULL : (*env)->NewStringUTF(env, (const char *)"+cArgName+");");
+ } else if (javaType.isArrayOfCompoundTypeWrappers() ||
+ ( javaType.isArray() && javaType.isNIOByteBufferArray() ) )
+ {
+ if( addLocalVar ) {
+ unit.emitln(" "+javaType.jniTypeName()+" "+javaArgName+";");
}
- unit.emitln(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNameArray()) + ";");
- unit.emitln(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);");
- unit.emitln(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {");
+ unit.emitln(" if (NULL == "+cArgName+") { "+javaArgName+" = NULL; } else {");
+ if ( !isReturnVal || returnValueLengthExpression == null ) {
+ throw new GlueGenException("Error while generating C code: No length specified for array returned from function for arg #" +
+ argIdx + ", "+cType.getDebugString()+", for "+
+ binding, binding.getCSymbol().getASTLocusTag());
+ } // TODO: Perhaps allow usage for non-return types, i.e. configure 'returnValueLengthExpression' for all arguments.
+ unit.emitln(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNameArray()) + ";");
+ unit.emitln(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);");
+ unit.emitln(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {");
final Type retType = binding.getCSymbol().getReturnType();
final Type pointerType = retType.getArrayBaseOrPointerTargetType();
- unit.emitln(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
- ", (*env)->NewDirectByteBuffer(env, (void *)_res[" + arrayIdx + "], sizeof(" + pointerType.getCName() + ")));");
+ unit.emitln(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
+ ", (*env)->NewDirectByteBuffer(env, (void *)"+cArgName+"[" + arrayIdx + "], sizeof(" + pointerType.getCName() + ")));");
+ unit.emitln(" }");
+ unit.emitln(" "+javaArgName+" = " + arrayRes + ";");
unit.emitln(" }");
- unit.emitln(" return " + arrayRes + ";");
- } else if (javaReturnType.isArray()) {
+ } else if (javaType.isArray()) {
// FIXME: must have user provide length of array in .cfg file
// by providing a constant value, input parameter, or
// expression which computes the array size (already present
// as ReturnValueCapacity, not yet implemented / tested here)
-
throw new GlueGenException(
- "Could not emit native code for function \"" + binding +
- "\": array return values for non-char types not implemented yet, for "+binding,
- binding.getCSymbol().getASTLocusTag());
+ "Could not emit native code for arg #"+argIdx+", "+cType.getDebugString()+", for " + binding +
+ ": array return values for non-char types not implemented yet.",
+ binding.getCSymbol().getASTLocusTag());
// FIXME: This is approximately what will be required here
//
@@ -1143,15 +1193,15 @@ public class CMethodBindingEmitter extends FunctionEmitter {
//unit().emit(arrayRes);
//unit().emit(", 0, ");
//unit().emit(arrayResLength);
- //unit().emitln(", _res);");
+ //unit().emitln(", "+cArgName+");");
//unit().emit(" return ");
//unit().emit(arrayRes);
//unit().emitln(";");
- } else {
- throw new GlueGenException("Unhandled return type: "+javaReturnType.getDebugString()+" for "+binding,
+ } else {
+ throw new GlueGenException("Unhandled return type: arg #"+argIdx+", C "+cType.getDebugString()+", java "+javaType.getDebugString()+" for "+binding,
binding.getCSymbol().getReturnType().getASTLocusTag());
- }
}
+ return true;
}
protected static String cThisArgumentName() {