aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/GlueGen_Mapping.html65
-rw-r--r--doc/GlueGen_Mapping.md70
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java42
-rw-r--r--src/java/com/jogamp/gluegen/JavaCallbackEmitter.java338
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java21
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java71
-rw-r--r--src/java/com/jogamp/gluegen/JavaType.java18
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java6
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java296
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.c9
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.h9
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.c68
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg40
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.h50
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>&lt;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>&lt;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: &lt;br&gt; &lt;code&gt;void MessageCallback11bInject(size_t id, long val)&lt;/code&gt;&lt;br&gt; */
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 -&gt; void (*T2_CallbackFunc12)(const LogMessage * usrParam) */
+ public static interface T2_CallbackFunc12 {
+ /** Interface to C language function: &lt;br&gt; &lt;code&gt;void callback(const LogMessage * usrParam)&lt;/code&gt;&lt;br&gt;Alias for: &lt;code&gt;T2_CallbackFunc12&lt;/code&gt; */
+ public void callback(LogMessage usrParam);
+ }
+
+ ...
+
+ /** Returns if callback is mapped for &lt;br&gt; &lt;code&gt; void SetLogCallBack(T2_CallbackFunc12 cbFunc)&lt;/code&gt; */
+ public boolean isSetLogCallBackMapped();
+
+ /** Returns T2_CallbackFunc12 callback for &lt;br&gt; &lt;code&gt; void SetLogCallBack(T2_CallbackFunc12 cbFunc)&lt;/code&gt; */
+ public T2_CallbackFunc12 getSetLogCallBack();
+
+ /** Releases callback data skipping toolkit API. Favor passing `null` callback ref to &lt;br&gt; &lt;code&gt; void SetLogCallBack(T2_CallbackFunc12 cbFunc)&lt;/code&gt; */
+ public void releaseSetLogCallBack();
+
+ /** Entry point (through function pointer) to C language function: &lt;br&gt; &lt;code&gt;void SetLogCallBack(T2_CallbackFunc12 cbFunc)&lt;/code&gt;&lt;br&gt; */
+ public void SetLogCallBack(T2_CallbackFunc12 cbFunc);
+
+ /** Entry point (through function pointer) to C language function: &lt;br&gt; &lt;code&gt;void LogCallBackInject(const LogMessage * message)&lt;/code&gt;&lt;br&gt; */
+ 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 */);
+