diff options
-rw-r--r-- | doc/GlueGen_Mapping.html | 65 | ||||
-rw-r--r-- | doc/GlueGen_Mapping.md | 70 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/CMethodBindingEmitter.java | 42 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaCallbackEmitter.java | 338 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaConfiguration.java | 21 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaEmitter.java | 71 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaType.java | 18 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java | 6 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java | 296 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test1.c | 9 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test1.h | 9 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.c | 68 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg | 40 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.h | 50 |
14 files changed, 940 insertions, 163 deletions
diff --git a/doc/GlueGen_Mapping.html b/doc/GlueGen_Mapping.html index 50bae2f..43f9219 100644 --- a/doc/GlueGen_Mapping.html +++ b/doc/GlueGen_Mapping.html @@ -476,6 +476,8 @@ <li><a href="#javacallback-example-11b-heterogeneous-pointerstruct-type">JavaCallback Example 11b (<em>Heterogeneous Pointer/Struct Type</em>)</a></li> + <li><a href="#javacallback-example-12-without-userparam">JavaCallback + Example 12 (Without UserParam)</a></li> </ul></li> <li><a href="#misc-configurations">Misc Configurations</a> <ul> @@ -2048,7 +2050,8 @@ use the same <code>CallbackFunctionType</code>.</p> <li><code>SetCallbackFunction</code>: <code>SetCallbackFunction</code> name of the native toolkit API responsible to set the callback</li> <li><code>SetCallback-UserParamIndex</code>: <code>UserParam</code> -parameter-index of the <code>SetCallbackFunction</code></li> +parameter-index of the <code>SetCallbackFunction</code> or +<code><0</code> to disable <code>UserParam</code></li> <li><code>CallbackFunctionType</code>: The native toolkit API typedef-name of the function-pointer-type, aka the callback type name</li> @@ -2056,7 +2059,8 @@ name</li> <code>userParam</code> parameter-index of the <code>CallbackFunctionType</code>, which allows to <a href="#struct-type-user-param-heterogeneous">indicate a heterogeneous -<code>UserParam</code></a></li> +<code>UserParam</code></a> or <code><0</code> to disable +<code>UserParam</code></li> <li><code>Callback-UserParamClass</code>: Optional <a href="#custom-callback-userparamclass">custom <em>UserParamClass</em></a> overriding the default <code>Object</code> @@ -2618,6 +2622,63 @@ users' <code>void*</code> pointer with the /** Entry point (through function pointer) to C language function: <br> <code>void MessageCallback11bInject(size_t id, long val)</code><br> */ public void MessageCallback11bInject(long id, long val);</code></pre> +<h3 id="javacallback-example-12-without-userparam">JavaCallback Example +12 (Without UserParam)</h3> +<p>This example demonstrates a JavaCallBack without user param and only +a global key.</p> +<p>The callback <code>T2_CallbackFunc12</code> is managed by the toolkit +and passed to the callback function, while user passes JavaCallback to +the registration method <code>SetLogCallBack(..)</code>.</p> +<p>C-API Header snipped</p> +<pre><code> 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);</code></pre> +<p>and the following GlueGen configuration</p> +<pre><code> ReturnsStringOnly LogMessage.Category + ReturnsStringOnly LogMessage.Message + + JavaCallbackDef SetLogCallBack -1 T2_CallbackFunc12 -1</code></pre> +<p>leading to the following interface</p> +<pre><code> + /** JavaCallback interface: T2_CallbackFunc12 -> void (*T2_CallbackFunc12)(const LogMessage * usrParam) */ + public static interface T2_CallbackFunc12 { + /** Interface to C language function: <br> <code>void callback(const LogMessage * usrParam)</code><br>Alias for: <code>T2_CallbackFunc12</code> */ + public void callback(LogMessage usrParam); + } + + ... + + /** Returns if callback is mapped for <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public boolean isSetLogCallBackMapped(); + + /** Returns T2_CallbackFunc12 callback for <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public T2_CallbackFunc12 getSetLogCallBack(); + + /** Releases callback data skipping toolkit API. Favor passing `null` callback ref to <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public void releaseSetLogCallBack(); + + /** Entry point (through function pointer) to C language function: <br> <code>void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code><br> */ + public void SetLogCallBack(T2_CallbackFunc12 cbFunc); + + /** Entry point (through function pointer) to C language function: <br> <code>void LogCallBackInject(const LogMessage * message)</code><br> */ + public void LogCallBackInject(LogMessage message);</code></pre> <p><em>TODO: Enhance documentation</em></p> <h2 id="misc-configurations">Misc Configurations</h2> <h3 diff --git a/doc/GlueGen_Mapping.md b/doc/GlueGen_Mapping.md index c1e71d5..1262082 100644 --- a/doc/GlueGen_Mapping.md +++ b/doc/GlueGen_Mapping.md @@ -826,9 +826,9 @@ as it is core to the semantic mapping of all resources. They also have to use th `JavaCallbackDef` attributes: - `SetCallbackFunction`: `SetCallbackFunction` name of the native toolkit API responsible to set the callback -- `SetCallback-UserParamIndex`: `UserParam` parameter-index of the `SetCallbackFunction` +- `SetCallback-UserParamIndex`: `UserParam` parameter-index of the `SetCallbackFunction` or `<0` to disable `UserParam` - `CallbackFunctionType`: The native toolkit API typedef-name of the function-pointer-type, aka the callback type name -- `CallbackFunction-UserParamIndex`: The `userParam` parameter-index of the `CallbackFunctionType`, which allows to [indicate a heterogeneous `UserParam`](#struct-type-user-param-heterogeneous) +- `CallbackFunction-UserParamIndex`: The `userParam` parameter-index of the `CallbackFunctionType`, which allows to [indicate a heterogeneous `UserParam`](#struct-type-user-param-heterogeneous) or `<0` to disable `UserParam` - `Callback-UserParamClass`: Optional [custom *UserParamClass*](#custom-callback-userparamclass) overriding the default `Object` for non-compound `UserParam` types. - `Callback-KeyClass`: Optional [custom *KeyClass*](#custom-callback-keyclass), providing the hash-map-key. @@ -1330,6 +1330,72 @@ leading to the following interface public void MessageCallback11bInject(long id, long val); ``` +### JavaCallback Example 12 (Without UserParam) + +This example demonstrates a JavaCallBack without user param and only a global key. + +The callback `T2_CallbackFunc12` is managed by the toolkit and passed to the callback function, while user passes JavaCallback to the registration method `SetLogCallBack(..)`. + + +C-API Header snipped +``` + 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); +``` + +and the following GlueGen configuration +``` + ReturnsStringOnly LogMessage.Category + ReturnsStringOnly LogMessage.Message + + JavaCallbackDef SetLogCallBack -1 T2_CallbackFunc12 -1 +``` + +leading to the following interface +``` + + /** JavaCallback interface: T2_CallbackFunc12 -> void (*T2_CallbackFunc12)(const LogMessage * usrParam) */ + public static interface T2_CallbackFunc12 { + /** Interface to C language function: <br> <code>void callback(const LogMessage * usrParam)</code><br>Alias for: <code>T2_CallbackFunc12</code> */ + public void callback(LogMessage usrParam); + } + + ... + + /** Returns if callback is mapped for <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public boolean isSetLogCallBackMapped(); + + /** Returns T2_CallbackFunc12 callback for <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public T2_CallbackFunc12 getSetLogCallBack(); + + /** Releases callback data skipping toolkit API. Favor passing `null` callback ref to <br> <code> void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code> */ + public void releaseSetLogCallBack(); + + /** Entry point (through function pointer) to C language function: <br> <code>void SetLogCallBack(T2_CallbackFunc12 cbFunc)</code><br> */ + public void SetLogCallBack(T2_CallbackFunc12 cbFunc); + + /** Entry point (through function pointer) to C language function: <br> <code>void LogCallBackInject(const LogMessage * message)</code><br> */ + public void LogCallBackInject(LogMessage message); +``` + *TODO: Enhance documentation* ## Misc Configurations diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java index e20a1cb..cbd33fd 100644 --- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java @@ -116,7 +116,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { // We need this in order to compute sizes of certain types protected MachineDataInfo machDesc; - private final CMethodBindingEmitter jcbCMethodEmitter; + private final CMethodBindingEmitter jcbFuncCMethodEmitter; private final JavaCallbackEmitter javaCallbackEmitter; /** @@ -154,13 +154,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { final JavaCallbackInfo javaCallback = cfg.setFuncToJavaCallbackMap.get(binding.getName()); if( null != javaCallback ) { // jcbNativeBasename = CodeGenUtils.capitalizeString( javaCallback.setFuncName+javaCallback.cbSimpleClazzName.replace("_", "") ); - jcbCMethodEmitter = new CMethodBindingEmitter(javaCallback.cbFuncBinding, - unit, javaPackageName, javaClassName, isOverloadedBinding, - isJavaMethodStatic, forImplementingMethodCall, - forIndirectBufferAndArrayImplementation, machDesc, configuration); + jcbFuncCMethodEmitter = new CMethodBindingEmitter(javaCallback.cbFuncBinding, + unit, javaPackageName, javaClassName, isOverloadedBinding, + isJavaMethodStatic, forImplementingMethodCall, + forIndirectBufferAndArrayImplementation, machDesc, configuration); javaCallbackEmitter = new JavaCallbackEmitter(cfg, binding, javaCallback, null); } else { - jcbCMethodEmitter = null; + jcbFuncCMethodEmitter = null; javaCallbackEmitter = null; } setCommentEmitter(defaultCommentEmitter); @@ -415,7 +415,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { @Override protected void emitAdditionalCode() { if( null != javaCallbackEmitter ) { - javaCallbackEmitter.emitCAdditionalCode(unit, jcbCMethodEmitter); + javaCallbackEmitter.emitCAdditionalCode(unit, jcbFuncCMethodEmitter); } } @@ -984,9 +984,11 @@ public class CMethodBindingEmitter extends FunctionEmitter { unit.emit(") + " + byteOffsetArgName(i) + ")"); } } else { - if (javaArgType.isString()) { unit.emit(STRING_CHARS_PREFIX); } + if ( javaArgType.isString() ) { + unit.emit(STRING_CHARS_PREFIX); + } unit.emit(binding.getArgumentName(i)); - if( null != javaCallbackEmitter ) { + if( !javaArgType.isString() && null != javaCallbackEmitter ) { javaCallbackEmitter.emitCOptArgumentSuffix(unit, i); } } @@ -1107,11 +1109,14 @@ public class CMethodBindingEmitter extends FunctionEmitter { unit.addTailCode(CCodeUnit.NewDirectByteBufferCopyUnitCode); } else if (javaType.isNIOBuffer() || javaType.isCompoundTypeWrapper()) { if( addLocalVar ) { - unit.emit(" "+javaType.jniTypeName()+" "+javaArgName+" = "); + unit.emitln(" "+javaType.jniTypeName()+" "+javaArgName+";"); } else { - unit.emit(" "+javaArgName+" = "); + unit.emitln(" "+javaArgName+";"); } - unit.emit("(NULL == "+cArgName+") ? NULL : (*env)->NewDirectByteBuffer(env, (void *)"+cArgName+", "); + unit.emitln(" if(NULL == "+cArgName+") {"); + unit.emitln(" "+javaArgName+" = NULL;"); + unit.emitln(" } else {"); + unit.emit (" "+javaArgName+" = (*env)->NewDirectByteBuffer(env, (void *)"+cArgName+", "); // See whether capacity has been specified if ( isReturnVal && returnValueCapacityExpression != null) { @@ -1168,13 +1173,14 @@ public class CMethodBindingEmitter extends FunctionEmitter { "value for function \"" + binding.getName() + "\". " + wmsg + " (sizeof(" + cType.getCName() + ")): " + binding); } } - 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(" */"); + 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(" */"); } + unit.emitln(" }"); } else if (javaType.isString()) { final boolean pascalString = javaType.isPascalStringVariant(); final String lenArgName; diff --git a/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java b/src/java/com/jogamp/gluegen/JavaCallbackEmitter.java index dbd38aa..01ffe8f 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+"() {"); @@ -359,7 +386,9 @@ public final class JavaCallbackEmitter { unit.emitln(" &&"); unit.emit (" "); } - if( jType.isPrimitive() || idx == info.setFuncUserParamIdx ) { + if( jType.isCompoundTypeWrapper() ) { + unit.emit(name+".getDirectBufferAddress() == o2."+name+".getDirectBufferAddress()"); + } else if( jType.isPrimitive() || idx == info.setFuncUserParamIdx ) { unit.emit(name+" == o2."+name); } else { unit.emit(name+".equals( o2."+name+" )"); @@ -392,6 +421,8 @@ public final class JavaCallbackEmitter { } else { unit.emitln(name+";"); } + } else if( jType.isCompoundTypeWrapper() ) { + unit.emitln("HashUtil.getAddrHash32_EqualDist( "+name+".getDirectBufferAddress() );"); } else { if( idx == info.setFuncUserParamIdx ) { unit.emitln("System.identityHashCode( "+name+" );"); @@ -416,23 +447,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 +485,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 +493,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 +584,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 +643,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,7 +660,9 @@ 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) { @@ -607,15 +672,22 @@ public final class JavaCallbackEmitter { 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 nativeCBFuncVarName = cbFuncArgName+"_native"; - final String nativeUserParamVarName = userParamArgName+"_native"; + final String userParamTypeName, nativeUserParamVarName; + if( userParamDefined ) { + userParamTypeName = info.cbFuncUserParamType.getCName(); + nativeUserParamVarName = binding.getArgumentName(info.setFuncUserParamIdx)+"_native"; + } else { + userParamTypeName = null; + nativeUserParamVarName = 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,30 +704,79 @@ 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 < info.cbFuncBinding.getNumArguments(); i++) { + final String baseArgName = CodeGenUtils.capitalizeString( info.cbFuncBinding.getArgumentName(i) ); + final JavaType currentJavaType = info.cbFuncBinding.getJavaArgumentType(i); + if( 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(); } - public void emitCAdditionalCode(final CodeUnit unit, final CMethodBindingEmitter jcbCMethodEmitter) { + /** + * Emit addition C code, i.e. global varialbles and static callback invocation + * @param unit output C code unit + * @param jcbFuncCMethodEmitter only used to access {@link CMethodBindingEmitter#emitBodyMapCToJNIType(int, boolean)}, a non-ideal hack! (FIXME) + */ + public void emitCAdditionalCode(final CodeUnit unit, final CMethodBindingEmitter jcbFuncCMethodEmitter) { final String jcbNativeBasename = CodeGenUtils.capitalizeString( info.setFuncName ); final String jcbFriendlyBasename = info.setFuncName+"("+info.cbSimpleClazzName+")"; final String staticBindingClazzVarName = "staticCBClazz"+jcbNativeBasename; 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, userParamArgName; + if( userParamDefined ) { + // final Type userParamType = javaCallback.cbFuncBinding.getCArgumentType(javaCallback.cbFuncUserParamIdx); + userParamTypeName = info.cbFuncUserParamType.getCName(); + userParamArgName = info.cbFuncBinding.getArgumentName(info.cbFuncUserParamIdx); + } else { + userParamTypeName = null; + userParamArgName = 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 < info.cbFuncBinding.getNumArguments(); i++) { + final String baseArgName = CodeGenUtils.capitalizeString( info.cbFuncBinding.getArgumentName(i) ); + final JavaType currentJavaType = info.cbFuncBinding.getJavaArgumentType(i); + if( 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 +789,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 < info.cbFuncBinding.getNumArguments(); i++) { + final String baseArgName = CodeGenUtils.capitalizeString( info.cbFuncBinding.getArgumentName(i) ); + final JavaType currentJavaType = info.cbFuncBinding.getJavaArgumentType(i); + if( 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;"); @@ -678,10 +809,12 @@ public final class JavaCallbackEmitter { // javaCallback.cbFuncCEmitter.emitBodyVariableDeclarations(); // javaCallback.cbFuncCEmitter.emitBodyUserVariableDeclarations(); // javaCallback.cbFuncCEmitter.emitBodyVariablePreCallSetup(); - emitJavaCallbackBodyCToJavaPreCall(jcbCMethodEmitter); + emitJavaCallbackBodyCToJavaPreCall(jcbFuncCMethodEmitter); // 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()); @@ -699,7 +832,7 @@ public final class JavaCallbackEmitter { } unit.emit("(*env)->CallStatic" + CodeGenUtils.capitalizeString( jretType.getName() ) +"Method(env, cbClazz, cbMethod, "); // javaCallback.cbFuncCEmitter.emitBodyPassCArguments(); - emitJavaCallbackBodyPassJavaArguments(unit, jcbCMethodEmitter.binding, null); //"NULL"); + emitJavaCallbackBodyPassJavaArguments(unit); unit.emitln(");"); unit.emitln(" if( (*env)->ExceptionCheck(env) ) {"); unit.emitln(" fprintf(stderr, \"Info: Callback '"+jcbFriendlyBasename+"': Exception in Java Callback caught:\\n\");"); @@ -717,7 +850,7 @@ public final class JavaCallbackEmitter { unit.emitln(); } - /* pp */ int emitJavaCallbackBodyCToJavaPreCall(final CMethodBindingEmitter ce) { + private int emitJavaCallbackBodyCToJavaPreCall(final CMethodBindingEmitter ce) { int count = 0; for (int i = 0; i < ce.binding.getNumArguments(); i++) { if( i == info.cbFuncUserParamIdx ) { @@ -730,18 +863,21 @@ public final class JavaCallbackEmitter { return count; } - /* pp */ int emitJavaCallbackBodyPassJavaArguments(final CodeUnit unit, final MethodBinding binding, final String userParamVarName) { + private int emitJavaCallbackBodyPassJavaArguments(final CodeUnit unit) { int count = 0; boolean needsComma = false; - for (int i = 0; i < binding.getNumArguments(); i++) { + for (int i = 0; i < info.cbFuncBinding.getNumArguments(); i++) { if (needsComma) { unit.emit(", "); needsComma = false; } - if( i == info.cbFuncUserParamIdx && null != userParamVarName ) { - unit.emit( userParamVarName ); + final String baseArgName = info.cbFuncBinding.getArgumentName(i); + final JavaType currentJavaType = info.cbFuncBinding.getJavaArgumentType(i); + if( i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) { + final String cBaseArgName = CodeGenUtils.capitalizeString( baseArgName ); + unit.emit( "(*env)->CallStaticObjectMethod(env, cbClazzArg" + cBaseArgName + ", cbMethodArg" + cBaseArgName + ", " + baseArgName + "_jni)" ); } else { - unit.emit( binding.getArgumentName(i) + "_jni" ); + 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..95e1480 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)); @@ -2511,4 +2518,10 @@ public class JavaConfiguration { /* pp */ final Map<String, JavaCallbackInfo> setFuncToJavaCallbackMap = new HashMap<String, JavaCallbackInfo>(); final Set<String> emittedJavaCallbackUserParamClasses = new HashSet<String>(); + /** Returns true if a method binding requires specific java callback code */ + final boolean requiresJavaCallbackCode(final String bindingName) { + final JavaCallbackInfo jcbi = setFuncToJavaCallbackMap.get(bindingName); + return null != jcbi && !jcbi.cbUserParamIsDefined; + } + } diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index 8310cda..fb310a9 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -465,9 +465,11 @@ 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 boolean needsJavaCallbackCode = cfg.requiresJavaCallbackCode( binding.getName() ); final boolean needsBody = isUnimplemented || binding.needsNIOWrappingOrUnwrapping() || binding.signatureUsesJavaPrimitiveArrays() || + needsJavaCallbackCode || null != prologue || null != epilogue; @@ -531,6 +533,7 @@ public class JavaEmitter implements GlueEmitter { final boolean hasPrologueOrEpilogue = cfg.javaPrologueForMethod(binding, false, false) != null || cfg.javaEpilogueForMethod(binding, false, false) != null ; + final boolean needsJavaCallbackCode = cfg.requiresJavaCallbackCode( binding.getName() ); if ( !cfg.isUnimplemented( cSymbol ) ) { // If we already generated a public native entry point for this @@ -541,7 +544,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 || needsJavaCallbackCode ) ) { final CodeUnit unit = (cfg.allStatic() ? javaUnit() : javaImplUnit()); @@ -588,7 +591,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 || needsJavaCallbackCode), !cfg.useNIODirectOnly(binding.getName()), machDescJava, getConfig()); prepCEmitter(binding.getName(), binding.getJavaReturnType(), cEmitter); @@ -1140,6 +1143,20 @@ public class JavaEmitter implements GlueEmitter { field + "\" in type \"" + structCTypeName + "\")", fieldType.getASTLocusTag()); } + if( !immutableField && !fieldType.isConst() ) { + // Setter + generateSetterSignature(javaUnit, MethodAccess.PUBLIC, false, false, fieldName, fieldType, Ownership.Parent, containingJTypeName, CodeGenUtils.capitalizeString(fieldName), null, fieldType.getName(), null, false, false, null, null, null); + javaUnit.emitln(" {"); + javaUnit.emitln(" final ByteBuffer bb = src.getBuffer();"); + javaUnit.emitln(" final int size = "+fieldName+"_size[mdIdx];"); + javaUnit.emitln(" final byte[] content = new byte[size];"); + javaUnit.emitln(" bb.get(content, 0, size);"); + javaUnit.emitln(" accessor.setBytesAt("+fieldName+"_offset[mdIdx], content);"); + javaUnit.emitln(" return this;"); + javaUnit.emitln(" }"); + javaUnit.emitln(); + } + // Getter generateGetterSignature(javaUnit, false, false, fieldName, fieldType, Ownership.Parent, fieldType.getName(), CodeGenUtils.capitalizeString(fieldName), null, false, false, null, null); javaUnit.emitln(" {"); javaUnit.emitln(" return " + fieldType.getName() + ".create( accessor.slice( " + @@ -1528,11 +1545,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 @@ -3131,8 +3148,7 @@ public class JavaEmitter implements GlueEmitter { final Type cArgType = sym.getArgumentType(i); final String cArgName = sym.getArgumentName(i); JavaType mappedType = typeToJavaType(cArgType, curMachDesc); - // System.out.println("C arg type -> \"" + cArgType + "\"" ); - // System.out.println(" Java -> \"" + mappedType + "\"" ); + int mapMode = 0; if( null != jcbi && jcbi.cbFuncTypeName.equals( cArgType.getName() ) && ( !jcbi.setFuncProcessed || i == jcbi.setFuncCBParamIdx ) ) @@ -3140,47 +3156,58 @@ public class JavaEmitter implements GlueEmitter { // Replace JavaCallback type with generated interface name jcbiSetFuncCBParamIdx=i; mappedType = JavaType.createForNamedClass( jcbi.cbFQClazzName ); + mapMode = 10; } else if( null != jcbi && i == jcbi.setFuncUserParamIdx && cArgType.isPointer() ) { // Replace userParam argument '<userParamType>*' if 'void*' with Object if( cArgType.getTargetType().isVoid() ) { if( jcbi.cbFuncUserParamType.isCompound() ) { mappedType = JavaType.createForClass(long.class); + mapMode = 20; } else if( null != jcbi.userParamClassName ) { mappedType = JavaType.createForNamedClass( jcbi.userParamClassName ); + mapMode = 21; } else { mappedType = JavaType.forObjectClass(); + mapMode = 22; } + } else { + // fallthrough intended } - } else if ( stringArgIndices != null && stringArgIndices.contains(i) ) { + } + if ( 0 == mapMode && stringArgIndices != null && stringArgIndices.contains(i) ) { // Take into account any ArgumentIsString configuration directives that apply // System.out.println("Forcing conversion of " + binding.getName() + " arg #" + i + " from byte[] to String "); - if (mappedType.isCVoidPointerType() || - mappedType.isCCharPointerType() || - mappedType.isCShortPointerType() || - mappedType.isNIOPointerBuffer() || - (mappedType.isArray() && - (mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass) || - (mappedType.getJavaClass() == ArrayTypes.shortBufferArrayClass))) { + if ( mappedType.isCVoidPointerType() || + mappedType.isCCharPointerType() || + mappedType.isCShortPointerType() || + mappedType.isNIOPointerBuffer() || + ( mappedType.isArray() && + ( mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass ) || + ( mappedType.getJavaClass() == ArrayTypes.shortBufferArrayClass ) ) ) + { // convert mapped type from: // void*, byte[], and short[] to String // ByteBuffer[] and ShortBuffer[] to String[] final boolean pascalString = cfg.pascalStringLengthIndex(sym, i) >= 0; if (mappedType.isArray() || mappedType.isNIOPointerBuffer()) { mappedType = javaStringType(ArrayTypes.stringArrayClass, pascalString); + mapMode = 30; } else { mappedType = javaStringType(String.class, pascalString); + mapMode = 31; } - } - else { - throw new GlueGenException( - "Cannot apply ArgumentIsString configuration directive to " + - "argument " + i + " of \"" + sym + "\": argument type is not " + - "a \"void*\", \"char *\", \"short *\", \"char**\", or \"short**\" equivalent", - sym.getASTLocusTag()); + } else { + mapMode = 99; + throw new GlueGenException( + "Cannot apply ArgumentIsString configuration directive to " + + "argument " + i + " of \"" + sym + "\": argument type is not " + + "a \"void*\", \"char *\", \"short *\", \"char**\", or \"short**\" equivalent", + sym.getASTLocusTag()); } } javaArgumentTypes.add(mappedType); - //System.out.println("During binding of [" + sym + "], added mapping from C type: " + cArgType + " to Java type: " + mappedType); + LOG.log(INFO, "BindFunc: {0}: added mapping ({1}) for {2} from C type: {3} to Java type: {4}", + sym.getName(), mapMode, cArgName, cArgType, mappedType); } if( null != jcbi ) { jcbi.setFuncProcessed(sym.getType(), jcbiSetFuncCBParamIdx); 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/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java index 5871fc0..2edfb5e 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java @@ -2052,6 +2052,12 @@ public class BaseClass extends SingletonJunitCase { /** Primitive.VariaValue.Struct.Pointer - write access */ private void chapter12_06bTestTKFieldVariaValueStructWriteAccess(final TK_Field model) { + { + final TK_Dimension val = createTKDim(0, 1, 50, 61); + model.setVariaStructElement(val); + Assert.assertTrue( equals(val, model.getVariaStructElement()) ); + } + Assert.assertEquals(1, TK_Field.getVariaStructPointerConstOneElemElemCount()); Assert.assertEquals(false, model.isVariaStructPointerConstOneElemNull()); { 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..92ab2f6 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; @@ -39,8 +40,12 @@ import com.jogamp.gluegen.test.junit.generation.Bindingtest2.AlEventCallback0Key import com.jogamp.gluegen.test.junit.generation.Bindingtest2.AlEventCallback1Key; import com.jogamp.gluegen.test.junit.generation.Bindingtest2.MessageCallback11aKey; import com.jogamp.gluegen.test.junit.generation.Bindingtest2.MessageCallback11bKey; +import com.jogamp.gluegen.test.junit.generation.Bindingtest2.MessageCallback13Key; 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_CallbackFunc12a; +import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc12b; +import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc13; import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest2Impl; import org.junit.AfterClass; @@ -1609,6 +1614,297 @@ public class Test4JavaCallback extends BaseClass { } } + /** + * Test Bindingtest2 with T2_CallbackFunc12a JavaCallback via SetLogCallBack12a() + */ + @Test + public void chapter12a() throws Exception { + final Bindingtest2 bt2 = new Bindingtest2Impl(); + + final AtomicReference<T2_Callback12LogMessage> messageExpected = new AtomicReference<>(null); + final AtomicReference<String> messageReturned = new AtomicReference<>(null); + final T2_CallbackFunc12a logCallBack = new T2_CallbackFunc12a() { + @Override + public void callback(final T2_Callback12LogMessage usrParam) { + assertEquals(messageExpected.get(), usrParam); // compare value, not object hash value (reference) + messageReturned.set("Result-"+usrParam.getMessage()); + } + }; + + bt2.SetLogCallBack12a(logCallBack); + messageReturned.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("TEST"); + logMessage.setMessage("Example"); + logMessage.setLevel(Bindingtest2.LOG_Info); + messageExpected.set(logMessage); + + bt2.LogCallBack12aInject(logMessage); + Assert.assertEquals(messageReturned.get(), "Result-Example"); + } + + messageReturned.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("IDK"); + logMessage.setMessage("John Doe is absent."); + logMessage.setLevel(Bindingtest2.LOG_Warning); + messageExpected.set(logMessage); + + bt2.LogCallBack12aInject(logMessage); + Assert.assertEquals(messageReturned.get(), "Result-John Doe is absent."); + } + + bt2.SetLogCallBack12a(null); + messageReturned.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("SANITY"); + logMessage.setMessage("Callback is now unset"); + logMessage.setLevel(Bindingtest2.LOG_Fatal); + messageExpected.set(logMessage); + + bt2.LogCallBack12aInject(logMessage); + Assert.assertEquals(messageReturned.get(), null); + } + } + /** + * Test Bindingtest2 with T2_CallbackFunc12a JavaCallback via SetLogCallBack12a() + */ + @Test + public void chapter12b() throws Exception { + final Bindingtest2 bt2 = new Bindingtest2Impl(); + + final AtomicReference<T2_Callback12LogMessage> expMessage = new AtomicReference<>(null); + final AtomicReference<String> hasReturnedMsg = new AtomicReference<>(null); + final T2_CallbackFunc12b logCallBack = new T2_CallbackFunc12b() { + int expParam0 = 1; + @Override + public void callback(final int param0, final T2_Callback12LogMessage usrParam) { + assertEquals(expMessage.get(), usrParam); // compare value, not object hash value (reference) + hasReturnedMsg.set("Result-"+usrParam.getMessage()); + Assert.assertEquals(expParam0++, param0); + } + }; + + bt2.SetLogCallBack12b(logCallBack); + hasReturnedMsg.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("TEST"); + logMessage.setMessage("Example"); + logMessage.setLevel(Bindingtest2.LOG_Info); + expMessage.set(logMessage); + + bt2.LogCallBack12bInject(logMessage, 1); + Assert.assertEquals("Result-Example", hasReturnedMsg.get()); + } + + hasReturnedMsg.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("IDK"); + logMessage.setMessage("John Doe is absent."); + logMessage.setLevel(Bindingtest2.LOG_Warning); + expMessage.set(logMessage); + + bt2.LogCallBack12bInject(logMessage, 2); + Assert.assertEquals("Result-John Doe is absent.", hasReturnedMsg.get()); + } + + bt2.SetLogCallBack12b(null); + hasReturnedMsg.set(null); + { + final T2_Callback12LogMessage logMessage = T2_Callback12LogMessage.create(); + logMessage.setCategory("SANITY"); + logMessage.setMessage("Callback is now unset"); + logMessage.setLevel(Bindingtest2.LOG_Fatal); + expMessage.set(logMessage); + + bt2.LogCallBack12bInject(logMessage, 3); + Assert.assertEquals(null, hasReturnedMsg.get()); + } + } + private static void assertEquals(final T2_Callback12LogMessage exp, final T2_Callback12LogMessage has) { + if( null == exp ) { + Assert.assertNull(has); + } else { + Assert.assertNotNull(has); + } + Assert.assertEquals(exp.getCategory(), has.getCategory()); + Assert.assertEquals(exp.getMessage(), has.getMessage()); + Assert.assertEquals(exp.getLevel(), has.getLevel()); + } + + /** + * Test Bindingtest2 with T2_CallbackFunc13 JavaCallback via MessageCallback13() + */ + @Test + public void chapter13() throws Exception { + final Bindingtest2 bt2 = new Bindingtest2Impl(); + + // + // Key 1 + // + final AtomicReference<String> hasReturnedMsgKey1 = new AtomicReference<>(null); + final T2_CallbackFunc13 callbackKey1 = new T2_CallbackFunc13() { + int localCallCount = 1; + + @Override + public void callback(final String msg1, final T2_Callback13UserType info, final String msg2, final T2_Callback13UserKey1 usrParamKey1, final long usrKey2) { + Assert.assertEquals(localCallCount, info.getANumber()); + final String strKey1 = String.valueOf( usrParamKey1.getKeyValue1() ); + final String strKey2 = String.valueOf( usrKey2 ); + Assert.assertEquals(strKey1, msg1); + Assert.assertEquals(strKey2, msg2); + hasReturnedMsgKey1.set("Result1-"+localCallCount+"-"+strKey1+"."+strKey2); + System.err.println("Callback: "+hasReturnedMsgKey1.get()); + localCallCount++; + } + }; + + // key 1 + 1 = ibdex 2 + final T2_Callback13UserKey1 key1a = T2_Callback13UserKey1.create(); + key1a.setKeyValue1(1); + final long key1b = 1; + final MessageCallback13Key expKey1 = new MessageCallback13Key(key1a, key1b); + bt2.MessageCallback13("a debug message - key2", callbackKey1, key1a, key1b); + + // + // Key 2 + // + final AtomicReference<String> hasReturnedMsgKey2 = new AtomicReference<>(null); + final T2_CallbackFunc13 callbackKey2 = new T2_CallbackFunc13() { + int localCallCount = 1; + + @Override + public void callback(final String msg1, final T2_Callback13UserType info, final String msg2, final T2_Callback13UserKey1 usrParamKey2, final long usrKey2) { + Assert.assertEquals(localCallCount, info.getANumber()); + final String strKey1 = String.valueOf( usrParamKey2.getKeyValue1() ); + final String strKey2 = String.valueOf( usrKey2 ); + Assert.assertEquals(strKey1, msg1); + Assert.assertEquals(strKey2, msg2); + hasReturnedMsgKey2.set("Result2-"+localCallCount+"-"+strKey1+"."+strKey2); + System.err.println("Callback: "+hasReturnedMsgKey2.get()); + localCallCount++; + } + }; + + // key 2 + 2 = ibdex 4 + final T2_Callback13UserKey1 key2a = T2_Callback13UserKey1.create(); + key2a.setKeyValue1(2); + final long key2b = 2; + final MessageCallback13Key expKey2 = new MessageCallback13Key(key2a, key2b); + bt2.MessageCallback13("a debug message - key2", callbackKey2, key2a, key2b); + + // Check keys + final Set<MessageCallback13Key> keys = bt2.getMessageCallback13Keys(); + Assert.assertNotNull(keys); + Assert.assertEquals(2, keys.size()); + { + System.err.println("XXX expKey1[key1a 0x"+Long.toHexString(key1a.getDirectBufferAddress())+", hash 0x"+Integer.toHexString(System.identityHashCode(key1a))+"]"); + System.err.println("XXX expKey1 hash 0x"+Integer.toHexString(expKey1.hashCode())); + + System.err.println("XXX expKey2[key1a 0x"+Long.toHexString(key2a.getDirectBufferAddress())+", hash 0x"+Integer.toHexString(System.identityHashCode(key2a))+"]"); + System.err.println("XXX expKey2 hash 0x"+Integer.toHexString(expKey2.hashCode())); + + final MessageCallback13Key[] keys0 = keys.toArray(new MessageCallback13Key[2]); + Assert.assertEquals(2, keys0.length); + final MessageCallback13Key hasKey1, hasKey2; + if( 1 == keys0[0].usrKey2 ) { + // keys0[0] -> hasKey1, keys0[1] -> hasKey2 + hasKey1 = keys0[0]; + hasKey2 = keys0[1]; + } else { + // keys0[0] -> hasKey2, keys0[1] -> hasKey1 + hasKey1 = keys0[1]; + hasKey2 = keys0[0]; + } + System.err.println("XXX hasKey1 hash 0x"+Integer.toHexString(hasKey1.hashCode())); + System.err.println("XXX hasKey2 hash 0x"+Integer.toHexString(hasKey2.hashCode())); + + Assert.assertEquals(key1a.getDirectBufferAddress(), hasKey1.usrParamKey1.getDirectBufferAddress()); + Assert.assertEquals(key1b, hasKey1.usrKey2); + Assert.assertEquals(expKey1, hasKey1); + Assert.assertEquals(expKey1.hashCode(), hasKey1.hashCode()); + final T2_CallbackFunc13 cb1 = bt2.getMessageCallback13(hasKey1); + Assert.assertNotNull(cb1); + final T2_Callback13UserKey1 up1 = bt2.getMessageCallback13UserParam(hasKey1); + Assert.assertNotNull(up1); + + Assert.assertEquals(key2a.getDirectBufferAddress(), hasKey2.usrParamKey1.getDirectBufferAddress()); + Assert.assertEquals(key2b, hasKey2.usrKey2); + Assert.assertEquals(expKey2, hasKey2); + Assert.assertEquals(expKey2.hashCode(), hasKey2.hashCode()); + final T2_CallbackFunc13 cb2 = bt2.getMessageCallback13(hasKey2); + Assert.assertNotNull(cb2); + final T2_Callback13UserKey1 up2 = bt2.getMessageCallback13UserParam(hasKey2); + Assert.assertNotNull(up2); + } + + // Send -> Key1 + int key1CallCount = 1; + final T2_Callback13UserType info1 = T2_Callback13UserType.create(); + hasReturnedMsgKey1.set(null); + { + final String expReturnedMsg = "Result1-"+key1CallCount+"-"+String.valueOf(key1a.getKeyValue1())+"."+String.valueOf(key1b); + info1.setANumber(key1CallCount); + bt2.InjectMessageCallback13(String.valueOf(key1a.getKeyValue1()), info1, String.valueOf(key1b), key1a, key1b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey1.get()); + key1CallCount++; + } + // Send -> Key2 + int key2CallCount = 1; + final T2_Callback13UserType info2 = T2_Callback13UserType.create(); + hasReturnedMsgKey2.set(null); + { + final String expReturnedMsg = "Result2-"+key2CallCount+"-"+String.valueOf(key2a.getKeyValue1())+"."+String.valueOf(key2b); + info2.setANumber(key2CallCount); + bt2.InjectMessageCallback13(String.valueOf(key2a.getKeyValue1()), info2, String.valueOf(key2b), key2a, key2b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey2.get()); + key2CallCount++; + } + + // Send -> Key1 + hasReturnedMsgKey1.set(null); + { + final String expReturnedMsg = "Result1-"+key1CallCount+"-"+String.valueOf(key1a.getKeyValue1())+"."+String.valueOf(key1b); + info1.setANumber(key1CallCount); + bt2.InjectMessageCallback13(String.valueOf(key1a.getKeyValue1()), info1, String.valueOf(key1b), key1a, key1b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey1.get()); + key1CallCount++; + } + // Send -> Key2 + hasReturnedMsgKey2.set(null); + { + final String expReturnedMsg = "Result2-"+key2CallCount+"-"+String.valueOf(key2a.getKeyValue1())+"."+String.valueOf(key2b); + info2.setANumber(key2CallCount); + bt2.InjectMessageCallback13(String.valueOf(key2a.getKeyValue1()), info2, String.valueOf(key2b), key2a, key2b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey2.get()); + key2CallCount++; + } + + // Send -> Key1 -> nil + bt2.MessageCallback13("turned off - key1", null, key1a, key1b); + hasReturnedMsgKey1.set(null); + { + final String expReturnedMsg = null; + info1.setANumber(key1CallCount); + bt2.InjectMessageCallback13(String.valueOf(key1a.getKeyValue1()), info1, String.valueOf(key1b), key1a, key1b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey1.get()); + } + // Send -> Key2 -> nil + bt2.MessageCallback13("turned off - key1", null, key2a, key2b); + hasReturnedMsgKey2.set(null); + { + final String expReturnedMsg = null; + info2.setANumber(key2CallCount); + bt2.InjectMessageCallback13(String.valueOf(key2a.getKeyValue1()), info2, String.valueOf(key2b), key2a, key2b); + Assert.assertEquals(expReturnedMsg, hasReturnedMsgKey2.get()); + } + } + 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/test1.c b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c index b74a171..c5ea388 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c @@ -690,7 +690,8 @@ typedef struct { TK_Dimension* constStructPointerCustomLen; int32_t constStructPointerCustomLenElemCount; - // Struct.VariaValue 2A + 5P = 7 + // Struct.VariaValue 1S + 2A + 5P = 8 + TK_Dimension variaStructElement; TK_Dimension variaStructArrayConstOneElem[1]; TK_Dimension variaStructArrayConstLen[3]; TK_Dimension* variaStructPointerConstOneElem; @@ -870,7 +871,11 @@ static TK_FieldMutable * createTKFieldMutable() { s->constStructPointerCustomLen[3].height = 164; s->constStructPointerCustomLenElemCount = 4; - // Struct.VariaValue.TK_Dimension 2A + 5P = 7 + // Struct.VariaValue.TK_Dimension 1S + 2A + 5P = 8 + s->variaStructElement.x = 47; + s->variaStructElement.y = 48; + s->variaStructElement.width = 49; + s->variaStructElement.height = 50; s->variaStructArrayConstOneElem[0].x = 51; s->variaStructArrayConstOneElem[0].y = 52; s->variaStructArrayConstOneElem[0].width = 53; diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h index 84045da..3b74040 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h @@ -505,7 +505,8 @@ typedef struct { const TK_Dimension* constStructPointerCustomLen; int32_t constStructPointerCustomLenElemCount; - // Struct.VariaValue 2A + 5P = 7 + // Struct.VariaValue 1S + 2A + 5P = 8 + TK_Dimension variaStructElement; TK_Dimension variaStructArrayConstOneElem[1]; TK_Dimension variaStructArrayConstLen[3]; TK_Dimension* variaStructPointerConstOneElem; @@ -606,7 +607,8 @@ typedef struct { const TK_Dimension* constStructPointerCustomLen; int32_t constStructPointerCustomLenElemCount; - // Struct.VariaValue 2A + 5P = 7 + // Struct.VariaValue 1S + 2A + 5P = 8 + TK_Dimension variaStructElement; TK_Dimension variaStructArrayConstOneElem[1]; TK_Dimension variaStructArrayConstLen[3]; TK_Dimension* variaStructPointerConstOneElem; @@ -707,7 +709,8 @@ typedef struct { const TK_Dimension* constStructPointerCustomLen; int32_t constStructPointerCustomLenElemCount; - // Struct.VariaValue 2A + 5P = 7 + // Struct.VariaValue 1S + 2A + 5P = 8 + TK_Dimension variaStructElement; TK_Dimension variaStructArrayConstOneElem[1]; TK_Dimension variaStructArrayConstLen[3]; TK_Dimension* variaStructPointerConstOneElem; 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..d181592 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,71 @@ void MessageCallback11bInject(size_t id, long val) { } } + +// +// + +static T2_CallbackFunc12a LogCallBack12a = NULL; + +void SetLogCallBack12a(T2_CallbackFunc12a cbFunc) { + LogCallBack12a = cbFunc; +} + +void LogCallBack12aInject(const T2_Callback12LogMessage* message) { + if ( NULL != LogCallBack12a ) { + fprintf(stderr, "XXX LogCallBack12aInject: func %p, message %p\n", LogCallBack12a, message); + fflush(NULL); + (*LogCallBack12a)(message); + } +} + +// +// + +static T2_CallbackFunc12b LogCallBack12b = NULL; + +void SetLogCallBack12b(T2_CallbackFunc12b cbFunc) { + LogCallBack12b = cbFunc; +} + +void LogCallBack12bInject(const T2_Callback12LogMessage* message, int param0) { + if ( NULL != LogCallBack12b ) { + fprintf(stderr, "XXX LogCallBack12bInject: func %p, message %p\n", LogCallBack12b, message); + fflush(NULL); + (*LogCallBack12b)(param0, message); + } +} + +// +// + +static const int MAX_C13_BUFFER = 10; + +static T2_CallbackFunc13 MessageCallback13_callback[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +void MessageCallback13(const char* debugMsg, T2_CallbackFunc13 cbFunc, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */) { + int id = usrParamKey1->keyValue1 + usrKey2; + if( id < 0 || MAX_C13_BUFFER <= id ) { + fprintf(stderr, "Error: MessageCallback13: id not in range [0..%d), is %d\n", MAX_C13_BUFFER, id); + } else { + MessageCallback13_callback[id] = cbFunc; + fprintf(stderr, "XXX MessageCallback13 id %d -> func %p, user %p, debugMsg '%s'\n", id, cbFunc, usrParamKey1, debugMsg); + } + fflush(NULL); +} + +void InjectMessageCallback13(const char* msg1, const T2_Callback13UserType* info, const char* msg2, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */) { + int id = usrParamKey1->keyValue1 + usrKey2; + if( id < 0 || MAX_C13_BUFFER <= id ) { + fprintf(stderr, "Error: InjectMessageCallback13: id not in range [0..%d), is %d\n", MAX_C13_BUFFER, id); + fflush(NULL); + return; + } + if( NULL != MessageCallback13_callback[id] ) { + fprintf(stderr, "XXX InjectMessageCallback13: id %d, func %p, user %p, msg1 '%s', msg2 '%s', key1 %d, key2 %zd\n", + id, MessageCallback13_callback[id], usrParamKey1, msg1, msg2, usrParamKey1->keyValue1, usrKey2); + fflush(NULL); + (*MessageCallback13_callback[id])(msg1, info, msg2, usrParamKey1, usrKey2); + } +} + 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..44b6468 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,43 @@ JavaCallbackKey MessageCallback11a 0 T2_CallbackFunc11 0 JavaCallbackDef MessageCallback11b 2 T2_CallbackFunc11 1 JavaCallbackKey MessageCallback11b 0 T2_CallbackFunc11 0 + +# T2_Callback12LogMessage +ReturnsStringOnly T2_Callback12LogMessage.Category +ReturnsStringOnly T2_Callback12LogMessage.Message + +# Begin JavaCallback +# +# typedef void ( * T2_CallbackFunc12a)(const T2_Callback12LogMessage* usrParam); +# void SetLogCallBack12a(T2_CallbackFunc12a cbFunc); +# void LogCallBack12aInject(const T2_Callback12LogMessage* message); +JavaCallbackDef SetLogCallBack12a -1 T2_CallbackFunc12a -1 +# +# End JavaCallback + +# Begin JavaCallback +# +# typedef void ( * T2_CallbackFunc12b)(int param0, const T2_Callback12LogMessage* usrParam1); +# void SetLogCallBack12b(T2_CallbackFunc12b cbFunc); +# void LogCallBack12bInject(const T2_Callback12LogMessage* message); +JavaCallbackDef SetLogCallBack12b -1 T2_CallbackFunc12b -1 +# +# End JavaCallback + +# Begin JavaCallback +# +# typedef void ( * T2_CallbackFunc13)(const char* msg1, const T2_Callback13UserType* info, const char* msg2, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); +# void MessageCallback13(const char* debugMsg, T2_CallbackFunc13 cbFunc, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); +# void InjectMessageCallback13(const char* msg1, const T2_Callback13UserType* info, const char* msg2, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); + +ArgumentIsString T2_CallbackFunc13 0 2 +ArgumentIsString InjectMessageCallback13 0 2 +ArgumentIsString MessageCallback13 0 +JavaCallbackDef MessageCallback13 2 T2_CallbackFunc13 3 +JavaCallbackKey MessageCallback13 2 3 T2_CallbackFunc13 3 4 +# +# End JavaCallback + CustomCCode #include "test2.h" Import com.jogamp.gluegen.test.junit.generation.Bindingtest2 @@ -187,6 +224,9 @@ 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.T2_Callback12LogMessage +Import com.jogamp.gluegen.test.junit.generation.T2_Callback13UserType +Import com.jogamp.gluegen.test.junit.generation.T2_Callback13UserKey1 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..653fcc2 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h @@ -70,7 +70,7 @@ void InjectMessageCallback01(size_t id, const char* msg); // ALBUFFERCALLBACKTYPESOFT (similar to OpenAL's AL_SOFT_callback_buffer) // // typedef void ( * ALBUFFERCALLBACKTYPESOFT)(int buffer, void *userptr, void *sampledata, int numbytes); -typedef void ( * ALBUFFERCALLBACKTYPESOFT)(int buffer, void *userptr, int sampledata, int numbytes); +typedef void ( * ALBUFFERCALLBACKTYPESOFT)(int buffer /* key */, void *userptr, int sampledata, int numbytes); void alBufferCallback0(int buffer /* key */, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, void *userptr); // void alBufferCallback0Inject(int buffer, void *sampledata, int numbytes); @@ -100,7 +100,7 @@ typedef struct { size_t id; } T2_Callback11UserType; -typedef void ( * T2_CallbackFunc11)(size_t id, const T2_Callback11UserType* usrParam, long val); +typedef void ( * T2_CallbackFunc11)(size_t id /* key */, const T2_Callback11UserType* usrParam, long val); void MessageCallback11a(size_t id /* key */, T2_CallbackFunc11 cbFunc, const T2_Callback11UserType* usrParam); void MessageCallback11aInject(size_t id, long val); @@ -108,3 +108,49 @@ 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 +} T2_Callback12LogLevel; + +typedef struct { + const char* Category; + const char* Message; + T2_Callback12LogLevel Level; +} T2_Callback12LogMessage; + +typedef void ( * T2_CallbackFunc12a)(const T2_Callback12LogMessage* usrParam); + +void SetLogCallBack12a(T2_CallbackFunc12a cbFunc); +void LogCallBack12aInject(const T2_Callback12LogMessage* message); + +typedef void ( * T2_CallbackFunc12b)(int param0, const T2_Callback12LogMessage* usrParam1); + +void SetLogCallBack12b(T2_CallbackFunc12b cbFunc); +void LogCallBack12bInject(const T2_Callback12LogMessage* message, int param0); + +// +// T2_CallbackFunc13 +// +typedef struct { + int aNumber; +} T2_Callback13UserType; + +typedef struct { + int keyValue1; +} T2_Callback13UserKey1; + +typedef void ( * T2_CallbackFunc13)(const char* msg1, const T2_Callback13UserType* info, const char* msg2, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); + +void MessageCallback13(const char* debugMsg, T2_CallbackFunc13 cbFunc, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); +void InjectMessageCallback13(const char* msg1, const T2_Callback13UserType* info, const char* msg2, const T2_Callback13UserKey1* usrParamKey1 /* key */, size_t usrKey2 /* key */); + |