summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Féry <[email protected]>2023-07-31 17:25:41 +0200
committerMathieu Féry <[email protected]>2023-07-31 17:25:41 +0200
commitad69716fda64b517c33ed847c4b215ea398aac99 (patch)
tree3a737b54f471d8c400d58633d1532420deb2ba53
parentfe21c87b24842d67df686b7c48fa36ed65a9afc9 (diff)
feat(callbackGenerator): Add basic management of callback without userData
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java2
-rw-r--r--src/java/com/jogamp/gluegen/JavaCallbackEmitter.java303
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java15
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java13
-rw-r--r--src/java/com/jogamp/gluegen/JavaType.java18
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java51
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.c18
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg14
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.h24
9 files changed, 350 insertions, 108 deletions
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index e20a1cb..9646774 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -427,7 +427,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
emitBodyUserVariableDeclarations();
emitBodyVariablePreCallSetup();
if( null != javaCallbackEmitter ) {
- javaCallbackEmitter.emitCSetFuncPreCall(unit);
+ javaCallbackEmitter.emitCSetFuncPreCall(unit, jcbCMethodEmitter);
}
emitBodyCallCFunction();
emitBodyUserVariableAssignments();
diff --git a/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java b/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java
index dbd38aa..5278db3 100644
--- a/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java
@@ -30,6 +30,8 @@ package com.jogamp.gluegen;
import com.jogamp.gluegen.JavaConfiguration.JavaCallbackInfo;
import com.jogamp.gluegen.cgram.types.Type;
+import java.nio.ByteBuffer;
+
public final class JavaCallbackEmitter {
final JavaConfiguration cfg;
final MethodBinding binding;
@@ -45,6 +47,8 @@ public final class JavaCallbackEmitter {
final JavaType cbFuncJavaReturnType;
final String jcbNextIDVarName;
+ final boolean userParamDefined;
+
final String setFuncCBArgName;
final Type setFuncUserParamCType;
final JavaType setFuncUserParamJType;
@@ -77,13 +81,24 @@ public final class JavaCallbackEmitter {
jcbNextIDVarName = "NEXT_"+capIfaceName+"_ID";
setFuncCBArgName = binding.getArgumentName(javaCallback.setFuncCBParamIdx);
- setFuncUserParamCType = mb.getCArgumentType(javaCallback.setFuncUserParamIdx);
- setFuncUserParamJType = mb.getJavaArgumentType(javaCallback.setFuncUserParamIdx);
- setFuncUserParamTypeName = setFuncUserParamJType.getName();
- setFuncUserParamArgName = binding.getArgumentName(javaCallback.setFuncUserParamIdx);
- userParamIsKey = info.setFuncKeyIndices.contains(info.setFuncUserParamIdx);
- if( !setFuncUserParamJType.isLong() ) {
+ userParamDefined = javaCallback.setFuncUserParamIdx >= 0;
+ if( !userParamDefined ) {
+ setFuncUserParamCType = null;
+ setFuncUserParamJType = null;
+ setFuncUserParamTypeName = null;
+ setFuncUserParamArgName = null;
+
+ userParamIsKey = false;
+ } else {
+ setFuncUserParamCType = mb.getCArgumentType(javaCallback.setFuncUserParamIdx);
+ setFuncUserParamJType = mb.getJavaArgumentType(javaCallback.setFuncUserParamIdx);
+ setFuncUserParamTypeName = setFuncUserParamJType.getName();
+ setFuncUserParamArgName = binding.getArgumentName(javaCallback.setFuncUserParamIdx);
+
+ userParamIsKey = info.setFuncKeyIndices.contains(info.setFuncUserParamIdx);
+ }
+ if( null != setFuncUserParamJType && !setFuncUserParamJType.isLong() ) {
if( setFuncUserParamJType.isCompoundTypeWrapper() ) {
userParamIsCompound = true;
userParamIsMappedToID = false;
@@ -99,16 +114,20 @@ public final class JavaCallbackEmitter {
userParamIDMapInstanceName = null;
}
- if( userParamIsCompound ) {
- userParamClassName = setFuncUserParamTypeName;
- } else if( null != javaCallback.userParamClassName ) {
- userParamClassName = javaCallback.userParamClassName;
+ if( userParamDefined ) {
+ if( userParamIsCompound ) {
+ userParamClassName = setFuncUserParamTypeName;
+ } else if( null != javaCallback.userParamClassName ) {
+ userParamClassName = javaCallback.userParamClassName;
+ } else {
+ userParamClassName = "Object";
+ }
} else {
- userParamClassName = "Object";
+ userParamClassName = null;
}
if( null != javaCallback.customKeyClassName ) {
- customKeyClass = true;;
+ customKeyClass = true;
KeyClassName = javaCallback.customKeyClassName;
useDataMap = true;
} else {
@@ -135,9 +154,11 @@ public final class JavaCallbackEmitter {
emitJavaBriefAPIDoc(unit, "Returns "+info.cbFuncTypeName+" callback ", "mapped to ", "", "for ");
unit.emitln(" public "+info.cbFuncTypeName+" get"+capIfaceName+"("+KeyClassName+" key);");
unit.emitln();
- emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
- unit.emitln(" public "+userParamClassName+" get"+capIfaceName+"UserParam("+KeyClassName+" key);");
- unit.emitln();
+ if( userParamDefined ) {
+ emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
+ unit.emitln(" public "+userParamClassName+" get"+capIfaceName+"UserParam("+KeyClassName+" key);");
+ unit.emitln();
+ }
emitJavaBriefAPIDoc(unit, "Releases all callback data ", "mapped via ", "", "skipping toolkit API. Favor passing `null` callback ref to ");
unit.emitln(" public int releaseAll"+capIfaceName+"();");
unit.emitln();
@@ -151,9 +172,11 @@ public final class JavaCallbackEmitter {
emitJavaBriefAPIDoc(unit, "Returns "+info.cbFuncTypeName+" callback ", "mapped to ", "", "for ");
unit.emitln(" public "+info.cbFuncTypeName+" get"+capIfaceName+"();");
unit.emitln();
- emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
- unit.emitln(" public "+userParamClassName+" get"+capIfaceName+"UserParam();");
- unit.emitln();
+ if( userParamDefined ) {
+ emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
+ unit.emitln(" public "+userParamClassName+" get"+capIfaceName+"UserParam();");
+ unit.emitln();
+ }
emitJavaBriefAPIDoc(unit, "Releases callback data ", "", "", "skipping toolkit API. Favor passing `null` callback ref to ");
unit.emitln(" public void release"+capIfaceName+"();");
unit.emitln();
@@ -189,14 +212,16 @@ public final class JavaCallbackEmitter {
unit.emitln(" }");
unit.emitln();
- emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
- unit.emitln(" public final "+userParamClassName+" get"+capIfaceName+"UserParam("+KeyClassName+" key) {");
- unit.emitln(" synchronized( "+lockInstanceName+" ) {");
- unit.emitln(" final "+DataClassName+" value = "+dataMapInstanceName+".get(key);");
- unit.emitln(" return null != value ? value.param : null;");
- unit.emitln(" }");
- unit.emitln(" }");
- unit.emitln();
+ if( userParamDefined ) {
+ emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
+ unit.emitln(" public final "+userParamClassName+" get"+capIfaceName+"UserParam("+KeyClassName+" key) {");
+ unit.emitln(" synchronized( "+lockInstanceName+" ) {");
+ unit.emitln(" final "+DataClassName+" value = "+dataMapInstanceName+".get(key);");
+ unit.emitln(" return null != value ? value.param : null;");
+ unit.emitln(" }");
+ unit.emitln(" }");
+ unit.emitln();
+ }
emitJavaBriefAPIDoc(unit, "Releases all callback data ", "mapped via ", "", "skipping toolkit API. Favor passing `null` callback ref to ");
unit.emitln(" public final int releaseAll"+capIfaceName+"() {");
unit.emitln(" synchronized( "+lockInstanceName+" ) {");
@@ -242,14 +267,16 @@ public final class JavaCallbackEmitter {
unit.emitln(" }");
unit.emitln();
- emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
- unit.emitln(" public final "+userParamClassName+" get"+capIfaceName+"UserParam() {");
- unit.emitln(" synchronized( "+lockInstanceName+" ) {");
- unit.emitln(" final "+DataClassName+" value = "+dataInstanceName+";");
- unit.emitln(" return null != value ? value.param : null;");
- unit.emitln(" }");
- unit.emitln(" }");
- unit.emitln();
+ if( userParamDefined ) {
+ emitJavaBriefAPIDoc(unit, "Returns user-param ", "mapped to ", "", "for ");
+ unit.emitln(" public final "+userParamClassName+" get"+capIfaceName+"UserParam() {");
+ unit.emitln(" synchronized( "+lockInstanceName+" ) {");
+ unit.emitln(" final "+DataClassName+" value = "+dataInstanceName+";");
+ unit.emitln(" return null != value ? value.param : null;");
+ unit.emitln(" }");
+ unit.emitln(" }");
+ unit.emitln();
+ }
emitJavaBriefAPIDoc(unit, "Releases callback data ", "", "", "skipping toolkit API. Favor passing `null` callback ref to ");
unit.emitln(" public final void release"+capIfaceName+"() {");
@@ -416,23 +443,32 @@ public final class JavaCallbackEmitter {
private final void emitJavaDataClass(final CodeUnit unit) {
unit.emitln(" private static class "+DataClassName+" {");
- unit.emitln(" // userParamArgCType "+setFuncUserParamCType);
- unit.emitln(" // userParamArgJType "+setFuncUserParamJType);
- unit.emitln(" final "+info.cbFuncTypeName+" func;");
- if( userParamIsMappedToID ) {
- unit.emitln(" final long paramID;");
- }
- unit.emitln(" final "+setFuncUserParamTypeName+" param;");
- unit.emit (" "+DataClassName+"(final "+info.cbFuncTypeName+" func, ");
- if( userParamIsMappedToID ) {
- unit.emit("final long paramID, ");
- }
- unit.emitln("final "+setFuncUserParamTypeName+" param) {");
+ unit.emitln(" final " + info.cbFuncTypeName + " func;");
+ if( userParamDefined ) {
+ unit.emitln(" // userParamArgCType "+setFuncUserParamCType);
+ unit.emitln(" // userParamArgJType "+setFuncUserParamJType);
+ unit.emitln(" final "+setFuncUserParamTypeName+" param;");
+ if( userParamIsMappedToID ) {
+ unit.emitln(" final long paramID;");
+ }
+ } else {
+ unit.emitln(" // No user param defined.");
+ }
+ unit.emit (" "+DataClassName+"(final "+info.cbFuncTypeName+" func");
+ if( userParamDefined ) {
+ if( userParamIsMappedToID ) {
+ unit.emit(", final long paramID");
+ }
+ unit.emit(", final "+setFuncUserParamTypeName+" param");
+ }
+ unit.emitln(") {");
unit.emitln(" this.func = func;");
- if( userParamIsMappedToID ) {
- unit.emitln(" this.paramID = paramID;");
+ if( userParamDefined ) {
+ if( userParamIsMappedToID ) {
+ unit.emitln(" this.paramID = paramID;");
+ }
+ unit.emitln(" this.param = param;");
}
- unit.emitln(" this.param = param;");
unit.emitln(" }");
unit.emitln(" }");
}
@@ -445,7 +481,7 @@ public final class JavaCallbackEmitter {
if( idx == info.cbFuncUserParamIdx ) {
buf.append("J");
} else {
- buf.append(jType.getDescriptor());
+ buf.append(jType.getDescriptor(cfg));
}
return true;
} else {
@@ -453,45 +489,60 @@ public final class JavaCallbackEmitter {
}
} );
buf.append(")");
- buf.append(cbFuncJavaReturnType.getDescriptor());
+ buf.append(cbFuncJavaReturnType.getDescriptor(cfg));
return buf.toString();
}
public final int appendJavaAdditionalJNIParameter(final StringBuilder buf) {
- buf.append("Class<?> staticCBClazz, String callbackSignature, long nativeUserParam");
+ buf.append("Class<?> staticCBClazz, String callbackSignature");
+ if( !userParamDefined ) {
+ return 2;
+ }
+ buf.append(", long nativeUserParam");
return 3;
}
public final int appendJavaAdditionalJNIArguments(final StringBuilder buf) {
- buf.append("this.getClass(), \"" + getJavaStaticCallbackSignature()+ "\", nativeUserParam");
+ buf.append("this.getClass(), \"" + getJavaStaticCallbackSignature() + "\"");
+ if( !userParamDefined ) {
+ return 2;
+ }
+ buf.append(", nativeUserParam");
return 3;
}
public void emitJavaSetFuncPreCall(final CodeUnit unit) {
- unit.emitln(" final long nativeUserParam;");
+ if( userParamDefined ) {
+ unit.emitln(" final long nativeUserParam;");
+ }
unit.emitln(" synchronized( "+lockInstanceName+" ) {");
- if( setFuncUserParamJType.isLong() ) {
- unit.emitln(" nativeUserParam = "+setFuncUserParamArgName+";");
- } else {
- unit.emitln(" if( null != "+setFuncUserParamArgName+" ) {");
- if( setFuncUserParamJType.isCompoundTypeWrapper() ) {
- // userParamIsCompound == true
- unit.emitln(" nativeUserParam = "+setFuncUserParamArgName+".getDirectBufferAddress();");
+ if( userParamDefined ) {
+ if( setFuncUserParamJType.isLong() ) {
+ unit.emitln(" nativeUserParam = "+setFuncUserParamArgName+";");
} else {
- // userParamIsMappedToID == true
- unit.emitln(" nativeUserParam = "+jcbNextIDVarName+"++;");
- unit.emitln(" if( 0 >= "+jcbNextIDVarName+" ) { "+jcbNextIDVarName+" = 1; }");
+ unit.emitln(" if( null != "+setFuncUserParamArgName+" ) {");
+ if( setFuncUserParamJType.isCompoundTypeWrapper() ) {
+ // userParamIsCompound == true
+ unit.emitln(" nativeUserParam = "+setFuncUserParamArgName+".getDirectBufferAddress();");
+ } else {
+ // userParamIsMappedToID == true
+ unit.emitln(" nativeUserParam = "+jcbNextIDVarName+"++;");
+ unit.emitln(" if( 0 >= "+jcbNextIDVarName+" ) { "+jcbNextIDVarName+" = 1; }");
+ }
+ unit.emitln(" } else {");
+ unit.emitln(" nativeUserParam = 0;");
+ unit.emitln(" }");
}
- unit.emitln(" } else {");
- unit.emitln(" nativeUserParam = 0;");
- unit.emitln(" }");
}
unit.emitln(" if( null != "+setFuncCBArgName+" ) {");
unit.emit (" add"+capIfaceName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), info.setFuncKeyIndices, true).toString()+
- "new "+DataClassName+"("+setFuncCBArgName+", ");
- if( userParamIsMappedToID ) {
- unit.emit("nativeUserParam, ");
+ "new "+DataClassName+"("+setFuncCBArgName);
+ if( userParamDefined ) {
+ if( userParamIsMappedToID ) {
+ unit.emit(", nativeUserParam");
+ }
+ unit.emit(", "+setFuncUserParamArgName);
}
- unit.emitln(setFuncUserParamArgName+"));");
+ unit.emitln("));");
unit.emitln(" } else { ");
unit.emitln(" // release a previously mapped instance ");
if( useDataMap ) {
@@ -529,17 +580,21 @@ public final class JavaCallbackEmitter {
} );
unit.emitln(") {");
final boolean useParamLocal[] = { false };
- if( mapNativePtrToCompound[0] ) {
- unit.emitln(" final "+origUserParamJType[0]+" "+info.cbFuncUserParamName+" = "+origUserParamJType[0]+".derefPointer(nativeUserParam);");
- useParamLocal[0] = true;
- } else if( userParamIsMappedToID && userParamIsKey ) {
- unit.emitln(" final "+userParamClassName+" "+info.cbFuncUserParamName+";");
+ if( userParamDefined ) {
+ if( mapNativePtrToCompound[0] ) {
+ unit.emitln(" final "+origUserParamJType[0]+" "+info.cbFuncUserParamName+" = "+origUserParamJType[0]+".derefPointer(nativeUserParam);");
+ useParamLocal[0] = true;
+ } else if( userParamIsMappedToID && userParamIsKey ) {
+ unit.emitln(" final "+userParamClassName+" "+info.cbFuncUserParamName+";");
+ }
}
unit.emitln(" final "+DataClassName+" value;");
unit.emitln(" synchronized( "+lockInstanceName+" ) {");
- if( userParamIsMappedToID && userParamIsKey && !mapNativePtrToCompound[0] ) {
- unit.emitln(" "+info.cbFuncUserParamName+" = ("+userParamClassName+") "+userParamIDMapInstanceName+".get(nativeUserParam);");
- useParamLocal[0] = true;
+ if( userParamDefined ) {
+ if( userParamIsMappedToID && userParamIsKey && !mapNativePtrToCompound[0] ) {
+ unit.emitln(" "+info.cbFuncUserParamName+" = ("+userParamClassName+") "+userParamIDMapInstanceName+".get(nativeUserParam);");
+ useParamLocal[0] = true;
+ }
}
if( useDataMap ) {
unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+info.cbFuncBinding.getJavaCallSelectArguments(new StringBuilder(), info.cbFuncKeyIndices, false).toString()+");");
@@ -584,7 +639,11 @@ public final class JavaCallbackEmitter {
//
public int appendCAdditionalParameter(final StringBuilder buf) {
- buf.append(", jclass staticCBClazz, jstring jcallbackSignature, jlong jnativeUserParam");
+ buf.append(", jclass staticCBClazz, jstring jcallbackSignature");
+ if( !userParamDefined ) {
+ return 2;
+ }
+ buf.append(", jlong jnativeUserParam");
return 3;
}
@@ -597,25 +656,29 @@ public final class JavaCallbackEmitter {
public void appendCAdditionalJNIDescriptor(final StringBuilder buf) {
JavaType.appendJNIDescriptor(buf, Class.class, false); // to account for the additional 'jclass staticCBClazz' parameter
JavaType.appendJNIDescriptor(buf, String.class, false); // to account for the additional 'jstring jcallbackSignature' parameter
- JavaType.appendJNIDescriptor(buf, long.class, false); // to account for the additional 'long nativeUserParam' parameter
+ if( userParamDefined ) {
+ JavaType.appendJNIDescriptor(buf, long.class, false); // to account for the additional 'long nativeUserParam' parameter
+ }
}
- public void emitCSetFuncPreCall(final CodeUnit unit) {
+ public void emitCSetFuncPreCall(final CodeUnit unit, final CMethodBindingEmitter jcbCMethodEmitter) {
final String jcbNativeBasename = CodeGenUtils.capitalizeString( info.setFuncName );
final String jcbFriendlyBasename = info.setFuncName+"("+info.cbSimpleClazzName+")";
final String staticBindingMethodName = "invoke"+jcbNativeBasename;
final String staticBindingClazzVarName = "staticCBClazz"+jcbNativeBasename;
final String staticBindingMethodIDVarName = "staticCBMethod"+jcbNativeBasename;
final String cbFuncArgName = binding.getArgumentName(info.setFuncCBParamIdx);
- final String userParamTypeName = info.cbFuncUserParamType.getCName();
- final String userParamArgName = binding.getArgumentName(info.setFuncUserParamIdx);
+ final String userParamTypeName = userParamDefined ? info.cbFuncUserParamType.getCName() : null;
+ final String userParamArgName = userParamDefined ? binding.getArgumentName(info.setFuncUserParamIdx) : null;
final String nativeCBFuncVarName = cbFuncArgName+"_native";
- final String nativeUserParamVarName = userParamArgName+"_native";
+ final String nativeUserParamVarName = userParamDefined ? userParamArgName+"_native" : null;
unit.emitln();
unit.emitln(" // JavaCallback handling");
unit.emitln(" if( NULL == staticCBClazz ) { (*env)->FatalError(env, \"NULL staticCBClazz passed to '"+jcbFriendlyBasename+"'\"); }");
unit.emitln(" "+info.cbFuncTypeName+" "+nativeCBFuncVarName+";");
- unit.emitln(" "+userParamTypeName+"* "+nativeUserParamVarName+";");
+ if( userParamDefined ) {
+ unit.emitln(" "+userParamTypeName+"* "+nativeUserParamVarName+";");
+ }
unit.emitln(" if( NULL != "+cbFuncArgName+" ) {");
unit.emitln(" if( NULL == "+staticBindingClazzVarName+" || NULL == "+staticBindingMethodIDVarName+" ) {");
unit.emitln(" jclass staticCBClazz2 = (*env)->NewGlobalRef(env, staticCBClazz);");
@@ -632,11 +695,39 @@ public final class JavaCallbackEmitter {
unit.emitln(" "+staticBindingClazzVarName+" = staticCBClazz2;");
unit.emitln(" "+staticBindingMethodIDVarName+" = cbMethodID;");
unit.emitln(" }");
+ final JavaType bbjt = JavaType.createForClass(ByteBuffer.class);
+ for (int i = 0; i < jcbCMethodEmitter.binding.getNumArguments(); i++) {
+ final String baseArgName = jcbCMethodEmitter.binding.getArgumentName(i);
+ final JavaType currentJavaType = jcbCMethodEmitter.binding.getJavaArgumentType(i);
+ if( i != info.setFuncUserParamIdx && i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) {
+ final String staticBindingClazzArgVarName = "staticCBArg" + baseArgName + "Clazz"+jcbNativeBasename;
+ final String staticBindingMethodIDArgVarName = "staticCBArg" + baseArgName + "Method"+jcbNativeBasename;
+ unit.emitln(" if( NULL == "+staticBindingClazzArgVarName+" || NULL == "+staticBindingMethodIDArgVarName+" ) {");
+ final String argClassDescriptor = currentJavaType.getDescriptor(cfg);
+ final String argClassRef = currentJavaType.getName(cfg);
+ final String argClassLocation = argClassRef.replace(".", "/");
+ unit.emitln(" jclass "+staticBindingClazzArgVarName+"2 = (*env)->FindClass(env, \""+argClassLocation+"\");");
+ unit.emitln(" if( NULL == "+staticBindingClazzArgVarName+"2 ) { (*env)->FatalError(env, \"Failed FindClass("+argClassLocation+") in '"+jcbFriendlyBasename+"'\"); }");
+ unit.emitln(" jmethodID "+staticBindingMethodIDArgVarName+"2 = (*env)->GetStaticMethodID(env, "+staticBindingClazzArgVarName+"2, \"create\", \"("+bbjt.getDescriptor()+")"+argClassDescriptor+"\");");
+ unit.emitln(" if( NULL == "+staticBindingMethodIDArgVarName+"2 ) {");
+ unit.emitln(" char cmsg[400];");
+ unit.emitln(" snprintf(cmsg, 400, \"Failed GetStaticMethodID of '"+argClassRef+".create("+bbjt.getDescriptor()+")"+argClassDescriptor+" in "+jcbFriendlyBasename+"'\");");
+ unit.emitln(" (*env)->FatalError(env, cmsg);");
+ unit.emitln(" }");
+ unit.emitln(" "+staticBindingClazzArgVarName+" = "+staticBindingClazzArgVarName+"2;");
+ unit.emitln(" "+staticBindingMethodIDArgVarName+" = "+staticBindingMethodIDArgVarName+"2;");
+ unit.emitln(" }");
+ }
+ }
unit.emitln(" "+nativeCBFuncVarName+" = func"+jcbNativeBasename+";");
- unit.emitln(" "+nativeUserParamVarName+" = ("+userParamTypeName+"*) jnativeUserParam;");
+ if( userParamDefined ) {
+ unit.emitln(" "+nativeUserParamVarName+" = ("+userParamTypeName+"*) jnativeUserParam;");
+ }
unit.emitln(" } else {");
unit.emitln(" "+nativeCBFuncVarName+" = NULL;");
- unit.emitln(" "+nativeUserParamVarName+" = NULL;");
+ if( userParamDefined ) {
+ unit.emitln(" "+nativeUserParamVarName+" = NULL;");
+ }
unit.emitln(" }");
unit.emitln();
@@ -649,13 +740,23 @@ public final class JavaCallbackEmitter {
final String staticBindingMethodIDVarName = "staticCBMethod"+jcbNativeBasename;
final String staticCallbackName = "func"+jcbNativeBasename;
// final Type userParamType = javaCallback.cbFuncBinding.getCArgumentType(javaCallback.cbFuncUserParamIdx);
- final String userParamTypeName = info.cbFuncUserParamType.getCName();
- final String userParamArgName = info.cbFuncBinding.getArgumentName(info.cbFuncUserParamIdx);
+ final String userParamTypeName = userParamDefined ? info.cbFuncUserParamType.getCName() : null ;
+ final String userParamArgName = userParamDefined ? info.cbFuncBinding.getArgumentName(info.cbFuncUserParamIdx) : null;
final Type cReturnType = info.cbFuncBinding.getCReturnType();
final JavaType jretType = info.cbFuncBinding.getJavaReturnType();
unit.emitln();
unit.emitln("static jclass "+staticBindingClazzVarName+" = NULL;");
unit.emitln("static jmethodID "+staticBindingMethodIDVarName+" = NULL;");
+ for (int i = 0; i < jcbCMethodEmitter.binding.getNumArguments(); i++) {
+ final String baseArgName = jcbCMethodEmitter.binding.getArgumentName(i);
+ final JavaType currentJavaType = jcbCMethodEmitter.binding.getJavaArgumentType(i);
+ if( i != info.setFuncUserParamIdx && i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) {
+ final String staticBindingClazzArgVarName = "staticCBArg" + baseArgName + "Clazz"+jcbNativeBasename;
+ final String staticBindingMethodIDArgVarName = "staticCBArg" + baseArgName + "Method"+jcbNativeBasename;
+ unit.emitln("static jclass "+staticBindingClazzArgVarName+" = NULL;");
+ unit.emitln("static jmethodID "+staticBindingMethodIDArgVarName+" = NULL;");
+ }
+ }
unit.emitln();
// javaCallback.cbFuncCEmitter.emitSignature();
unit.emit("static "+cReturnType.getCName()+" "+staticCallbackName+"(");
@@ -668,6 +769,16 @@ public final class JavaCallbackEmitter {
unit.emitln(" JNIEnv* env = JVMUtil_GetJNIEnv(1 /* daemon */, &detachJVM);");
unit.emitln(" jclass cbClazz = "+staticBindingClazzVarName+";");
unit.emitln(" jmethodID cbMethod = "+staticBindingMethodIDVarName+";");
+ for (int i = 0; i < jcbCMethodEmitter.binding.getNumArguments(); i++) {
+ final String baseArgName = jcbCMethodEmitter.binding.getArgumentName(i);
+ final JavaType currentJavaType = jcbCMethodEmitter.binding.getJavaArgumentType(i);
+ if( i != info.setFuncUserParamIdx && i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) {
+ final String staticBindingClazzArgVarName = "staticCBArg" + baseArgName + "Clazz"+jcbNativeBasename;
+ final String staticBindingMethodIDArgVarName = "staticCBArg" + baseArgName + "Method"+jcbNativeBasename;
+ unit.emitln(" jclass cbClazzArg" + baseArgName+" = "+staticBindingClazzArgVarName+";");
+ unit.emitln(" jmethodID cbMethodArg" + baseArgName+" = "+staticBindingMethodIDArgVarName+";");
+ }
+ }
unit.emitln(" if( NULL == env || NULL == cbClazz || NULL == cbMethod ) {");
if( !cReturnType.isVoid() ) {
unit.emitln(" return 0;");
@@ -681,7 +792,9 @@ public final class JavaCallbackEmitter {
emitJavaCallbackBodyCToJavaPreCall(jcbCMethodEmitter);
// javaCallback.cbFuncCEmitter.emitBodyCallCFunction();
- unit.emitln(" "+userParamTypeName+"* "+userParamArgName+"_jni = ("+userParamTypeName+"*) "+userParamArgName+";");
+ if( userParamDefined ) {
+ unit.emitln(" "+userParamTypeName+"* "+userParamArgName+"_jni = ("+userParamTypeName+"*) "+userParamArgName+";");
+ }
unit.emitln(" // C Params: "+info.cbFuncBinding.getCParameterList(new StringBuilder(), false, null).toString());
unit.emitln(" // J Params: "+info.cbFuncBinding.getJavaParameterList(new StringBuilder()).toString());
@@ -741,7 +854,13 @@ public final class JavaCallbackEmitter {
if( i == info.cbFuncUserParamIdx && null != userParamVarName ) {
unit.emit( userParamVarName );
} else {
- unit.emit( binding.getArgumentName(i) + "_jni" );
+ final String baseArgName = binding.getArgumentName(i);
+ final JavaType currentJavaType = binding.getJavaArgumentType(i);
+ if( i != info.setFuncUserParamIdx && i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) {
+ unit.emit( "(*env)->CallStaticObjectMethod(env, cbClazzArg" + baseArgName + ", cbMethodArg" + baseArgName + ", " + baseArgName + "_jni)" );
+ } else {
+ unit.emit( baseArgName + "_jni" );
+ }
}
needsComma = true;
++count;
diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java
index f5242b8..6d0eae5 100644
--- a/src/java/com/jogamp/gluegen/JavaConfiguration.java
+++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java
@@ -2423,6 +2423,8 @@ public class JavaConfiguration {
final String cbFuncUserParamName;
final Type cbFuncUserParamType;
+ final boolean cbUserParamIsDefined;
+
final String setFuncName;
final List<Integer> setFuncKeyIndices;
final int setFuncUserParamIdx;
@@ -2442,7 +2444,8 @@ public class JavaConfiguration {
this.staticCBMethodSignature = staticCBMethodSignature;
this.cbFuncType = cbFuncType;
this.cbFuncBinding = cbFuncBinding;
- {
+ this.cbUserParamIsDefined = setFuncUserParamIdx >= 0;
+ if( cbUserParamIsDefined ) {
int paramIdx = -2;
Type paramType = null;
String paramName = null;
@@ -2456,10 +2459,14 @@ public class JavaConfiguration {
}
}
this.cbFuncUserParamIdx = paramIdx;
- this.cbFuncKeyIndices = cbFuncKeyIndices;
this.cbFuncUserParamName = paramName;
this.cbFuncUserParamType = paramType;
+ } else {
+ this.cbFuncUserParamIdx = -1;
+ this.cbFuncUserParamName = null;
+ this.cbFuncUserParamType = null;
}
+ this.cbFuncKeyIndices = cbFuncKeyIndices;
this.setFuncName = setFuncName;
this.setFuncKeyIndices = setFuncKeyIndices;
this.setFuncUserParamIdx = setFuncUserParamIdx;
@@ -2499,9 +2506,9 @@ public class JavaConfiguration {
@Override
public String toString() {
- return String.format("JavaCallbackInfo[cbFunc[%s%s, userParam[idx %d, '%s', %s, keys %s], set[%s(ok %b, cbIdx %d, upIdx %d, keys %s], Class[UserParam '%s', Key '%s'], %s]",
+ return String.format("JavaCallbackInfo[cbFunc[%s%s, userParam[defined %b, idx %d, '%s', %s, keys %s], set[%s(ok %b, cbIdx %d, upIdx %d, keys %s], Class[UserParam '%s', Key '%s'], %s]",
cbFuncTypeName, staticCBMethodSignature,
- cbFuncUserParamIdx, cbFuncUserParamName, cbFuncUserParamType.getSignature(null).toString(), cbFuncKeyIndices.toString(),
+ cbUserParamIsDefined, cbFuncUserParamIdx, cbFuncUserParamName, cbUserParamIsDefined ? cbFuncUserParamType.getSignature(null).toString() : null, cbFuncKeyIndices.toString(),
setFuncName, setFuncProcessed, setFuncCBParamIdx, setFuncUserParamIdx,
setFuncKeyIndices.toString(), userParamClassName, customKeyClassName,
cbFuncType.toString(cbFuncTypeName, false, true));
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index 576e9bc..75fe77c 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -465,9 +465,12 @@ public class JavaEmitter implements GlueEmitter {
final boolean isUnimplemented = cfg.isUnimplemented(cSymbol);
final List<String> prologue = cfg.javaPrologueForMethod(binding, false, false);
final List<String> epilogue = cfg.javaEpilogueForMethod(binding, false, false);
+ final JavaCallbackInfo jcbi = cfg.setFuncToJavaCallbackMap.get(binding.getName());
+ final boolean needsIntermediateOperation = null != jcbi && !jcbi.cbUserParamIsDefined;
final boolean needsBody = isUnimplemented ||
binding.needsNIOWrappingOrUnwrapping() ||
binding.signatureUsesJavaPrimitiveArrays() ||
+ needsIntermediateOperation ||
null != prologue ||
null != epilogue;
@@ -531,6 +534,8 @@ public class JavaEmitter implements GlueEmitter {
final boolean hasPrologueOrEpilogue =
cfg.javaPrologueForMethod(binding, false, false) != null ||
cfg.javaEpilogueForMethod(binding, false, false) != null ;
+ final JavaCallbackInfo jcbi = cfg.setFuncToJavaCallbackMap.get(binding.getName());
+ final boolean needsIntermediateOperation = null != jcbi && !jcbi.cbUserParamIsDefined;
if ( !cfg.isUnimplemented( cSymbol ) ) {
// If we already generated a public native entry point for this
@@ -541,7 +546,7 @@ public class JavaEmitter implements GlueEmitter {
// the private native entry point for it along with the version
// taking only NIO buffers
if ( !binding.signatureUsesJavaPrimitiveArrays() &&
- ( binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue )
+ ( binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue || needsIntermediateOperation )
)
{
final CodeUnit unit = (cfg.allStatic() ? javaUnit() : javaImplUnit());
@@ -588,7 +593,7 @@ public class JavaEmitter implements GlueEmitter {
cfg.implClassName(),
true, // NOTE: we always disambiguate with a suffix now, so this is optional
cfg.allStatic(),
- (binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue),
+ (binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue || needsIntermediateOperation),
!cfg.useNIODirectOnly(binding.getName()),
machDescJava, getConfig());
prepCEmitter(binding.getName(), binding.getJavaReturnType(), cEmitter);
@@ -1528,11 +1533,11 @@ public class JavaEmitter implements GlueEmitter {
methodSignature.append("(");
for(int i=0; i<mb.getNumArguments(); ++i) {
final JavaType t = mb.getJavaArgumentType(i);
- methodSignature.append(t.getDescriptor());
+ methodSignature.append(t.getDescriptor(cfg));
}
methodSignature.append(")");
final JavaType rt = mb.getJavaReturnType();
- methodSignature.append(rt.getDescriptor());
+ methodSignature.append(rt.getDescriptor(cfg));
}
// JavaTypes representing C pointers in the initial
diff --git a/src/java/com/jogamp/gluegen/JavaType.java b/src/java/com/jogamp/gluegen/JavaType.java
index 6fb9a17..d58eca5 100644
--- a/src/java/com/jogamp/gluegen/JavaType.java
+++ b/src/java/com/jogamp/gluegen/JavaType.java
@@ -282,6 +282,10 @@ public class JavaType {
* Returns the Java type name corresponding to this type.
*/
public String getName() {
+ return getName(null);
+ }
+
+ public String getName(final JavaConfiguration cfg) {
if (clazz != null) {
if (clazz.isArray()) {
return arrayName(clazz);
@@ -289,29 +293,29 @@ public class JavaType {
return clazz.getName();
}
if( clazzName != null ) {
- return clazzName;
+ return (null != cfg ? (cfg.packageForStruct(clazzName) + ".") : "") + clazzName;
}
if (elementType != null) {
return elementType.getName();
}
- return structName;
+ return (null != cfg ? (cfg.packageForStruct(clazzName) + ".") : "") + structName;
}
/**
* Returns the descriptor (internal type signature) corresponding to this type.
*/
public String getDescriptor() {
- // FIXME: this is not completely accurate at this point (for
- // example, it knows nothing about the packages for compound
- // types)
+ return getDescriptor(null);
+ }
+ public String getDescriptor(final JavaConfiguration cfg) {
if (clazz != null) {
return descriptor(clazz);
}
if( null != clazzName ) {
- return descriptor(clazzName);
+ return descriptor((null != cfg ? (cfg.packageForStruct(clazzName) + ".") : "") + clazzName);
}
if( null != structName ) {
- return descriptor(structName);
+ return descriptor((null != cfg ? (cfg.packageForStruct(structName) + ".") : "") + structName);
}
if (elementType != null) {
if(elementType.getName()==null) {
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java
index 09b51c7..61a8412 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java
@@ -30,6 +30,7 @@ package com.jogamp.gluegen.test.junit.generation;
import java.io.IOException;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import com.jogamp.common.os.NativeLibrary;
import com.jogamp.gluegen.test.junit.generation.Bindingtest2.ALBUFFERCALLBACKTYPESOFT;
@@ -41,6 +42,7 @@ import com.jogamp.gluegen.test.junit.generation.Bindingtest2.MessageCallback11aK
import com.jogamp.gluegen.test.junit.generation.Bindingtest2.MessageCallback11bKey;
import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc01;
import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc11;
+import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc12;
import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest2Impl;
import org.junit.AfterClass;
@@ -1609,6 +1611,55 @@ public class Test4JavaCallback extends BaseClass {
}
}
+ /**
+ * Test Bindingtest2 with T2_CallbackFunc12 JavaCallback via SetLogCallBack()
+ */
+ @Test
+ public void chapter12() throws Exception {
+ final Bindingtest2 bt2 = new Bindingtest2Impl();
+
+ final AtomicReference<LogMessage> messageSupplied = new AtomicReference<>(null);
+ final T2_CallbackFunc12 logCallBack = new T2_CallbackFunc12() {
+ @Override
+ public void callback(final LogMessage usrParam) {
+ Assert.assertEquals(messageSupplied.get(), usrParam);
+ }
+ };
+ bt2.SetLogCallBack(logCallBack);
+
+ {
+ final LogMessage logMessage = LogMessage.create();
+ logMessage.setCategory("TEST");
+ logMessage.setMessage("Example");
+ logMessage.setLevel(Bindingtest2.LOG_Info);
+ messageSupplied.set(logMessage);
+
+ bt2.LogCallBackInject(logMessage);
+ }
+
+ {
+ final LogMessage logMessage = LogMessage.create();
+ logMessage.setCategory("IDK");
+ logMessage.setMessage("John Doe is absent.");
+ logMessage.setLevel(Bindingtest2.LOG_Warning);
+ messageSupplied.set(logMessage);
+
+ bt2.LogCallBackInject(logMessage);
+ }
+
+ bt2.SetLogCallBack(null);
+
+ {
+ final LogMessage logMessage = LogMessage.create();
+ logMessage.setCategory("SANITY");
+ logMessage.setMessage("Callback is now unset");
+ logMessage.setLevel(Bindingtest2.LOG_Fatal);
+ messageSupplied.set(logMessage);
+
+ bt2.LogCallBackInject(logMessage);
+ }
+ }
+
static private String toHexString(final int v) { return "0x"+Integer.toHexString(v); }
public static void main(final String args[]) throws IOException {
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c
index b9ad4aa..66e562f 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c
@@ -323,3 +323,21 @@ void MessageCallback11bInject(size_t id, long val) {
}
}
+
+//
+//
+
+static T2_CallbackFunc12 LogCallBack = NULL;
+
+void SetLogCallBack(T2_CallbackFunc12 cbFunc) {
+ LogCallBack = cbFunc;
+}
+
+void LogCallBackInject(const LogMessage* message) {
+ if ( NULL != LogCallBack ) {
+ fprintf(stderr, "XXX LogCallBackInject: func %p, message %p\n", &LogCallBack, &message);
+ fflush(NULL);
+ (*LogCallBack)(message);
+ }
+}
+
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg
index fdad264..51eb0ae 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg
@@ -179,6 +179,19 @@ JavaCallbackKey MessageCallback11a 0 T2_CallbackFunc11 0
JavaCallbackDef MessageCallback11b 2 T2_CallbackFunc11 1
JavaCallbackKey MessageCallback11b 0 T2_CallbackFunc11 0
+
+ReturnsStringOnly LogMessage.Category
+ReturnsStringOnly LogMessage.Message
+
+# Begin JavaCallback
+#
+# typedef void ( * T2_CallbackFunc12)(const LogMessage* usrParam);
+# void SetLogCallBack(T2_CallbackFunc12 cbFunc);
+# void LogCallBackInject(LogMessage message);
+JavaCallbackDef SetLogCallBack -1 T2_CallbackFunc12 -1
+#
+# End JavaCallback
+
CustomCCode #include "test2.h"
Import com.jogamp.gluegen.test.junit.generation.Bindingtest2
@@ -187,6 +200,7 @@ Import com.jogamp.gluegen.test.junit.generation.T2_InitializeOptions
Import com.jogamp.gluegen.test.junit.generation.T2_ThreadAffinity
Import com.jogamp.gluegen.test.junit.generation.T2_UserData
Import com.jogamp.gluegen.test.junit.generation.T2_Callback11UserType
+Import com.jogamp.gluegen.test.junit.generation.LogMessage
Import com.jogamp.gluegen.test.junit.generation.Test4JavaCallback.ALCcontext
CustomJavaCode Bindingtest2Impl private static Bindingtest2ProcAddressTable _table = new Bindingtest2ProcAddressTable();
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h
index ddd8c8a..ec46885 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h
@@ -108,3 +108,27 @@ void MessageCallback11aInject(size_t id, long val);
void MessageCallback11b(size_t id /* key */, T2_CallbackFunc11 cbFunc, void* Data);
void MessageCallback11bInject(size_t id, long val);
+//
+// T2_CallbackFunc12
+//
+
+typedef enum {
+ LOG_Off = 0,
+ LOG_Fatal = 100,
+ LOG_Error = 200,
+ LOG_Warning = 300,
+ LOG_Info = 400,
+ LOG_Verbose = 500,
+ LOG_VeryVerbose = 600
+} LogLevel;
+
+typedef struct {
+ const char* Category;
+ const char* Message;
+ LogLevel Level;
+} LogMessage;
+
+typedef void ( * T2_CallbackFunc12)(const LogMessage* usrParam);
+
+void SetLogCallBack(T2_CallbackFunc12 cbFunc);
+void LogCallBackInject(const LogMessage* message);