aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/GlueGen_Mapping.html285
-rw-r--r--doc/GlueGen_Mapping.md97
-rw-r--r--make/build-test.xml8
-rwxr-xr-xmake/scripts/runtest.sh3
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java123
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java10
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test2.java148
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.c59
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg30
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test2.h35
10 files changed, 631 insertions, 167 deletions
diff --git a/doc/GlueGen_Mapping.html b/doc/GlueGen_Mapping.html
index b86d294..d3f7aef 100644
--- a/doc/GlueGen_Mapping.html
+++ b/doc/GlueGen_Mapping.html
@@ -430,12 +430,14 @@
<li><a href="#gluegen-struct-settings">GlueGen Struct
Settings</a></li>
<li><a href="#struct-mapping-notes">Struct Mapping Notes</a></li>
+ <li><a href="#struct-setter-pseudo-code">Struct Setter
+ Pseudo-Code</a></li>
<li><a href="#struct-java-signature-table">Struct Java Signature
Table</a></li>
<li><a href="#struct-java-signature-examples">Struct Java Signature
Examples</a></li>
- <li><a href="#struct-setter-pseudo-code">Struct Setter
- Pseudo-Code</a></li>
+ <li><a href="#struct-function-pointer-support">Struct Function Pointer
+ Support</a></li>
</ul></li>
<li><a href="#platform-header-files">Platform Header Files</a></li>
<li><a href="#pre-defined-macros">Pre-Defined Macros</a></li>
@@ -1043,6 +1045,121 @@ underlying API shall utilize <code>setVal(..)</code> and
<li><p>To release native memory with <em>java ownership</em>, i.e. a
native ByteBuffer, <code>releaseVal()</code> can be used.</p></li>
</ul>
+<h3 id="struct-setter-pseudo-code">Struct Setter Pseudo-Code</h3>
+<h4 id="overview-1">Overview</h4>
+<p>In general we have the following few cases</p>
+<ul>
+<li><p>Array owned by parent struct itself</p>
+<ul>
+<li><code>int32_t val[10]</code>
+<ul>
+<li>Setter of <code>val</code> within range, keeping memory</li>
+</ul></li>
+<li><code>const int32_t val[10]</code>
+<ul>
+<li>No setter allowed due to const value</li>
+</ul></li>
+</ul></li>
+<li><p>Referenced Memory (array) owned by Java</p>
+<ul>
+<li><code>int32_t* val</code>
+<ul>
+<li>Setter within range, keeping memory, or replacing memory</li>
+</ul></li>
+<li><code>const int32_t* val</code>
+<ul>
+<li>Setter replacing memory, since memory is non-const but value is
+const</li>
+</ul></li>
+</ul></li>
+<li><p>Referenced Memory (array) owned by Native Code due to set
+<em>ConstElemCount</em></p>
+<ul>
+<li><code>int32_t* val</code>
+<ul>
+<li>Setter of <code>val</code> within range, keeping memory owned by
+native code</li>
+</ul></li>
+<li><code>const int32_t* val</code>
+<ul>
+<li>No setter allowed, since memory is owned by native code and value is
+const</li>
+</ul></li>
+</ul></li>
+</ul>
+<h4 id="implemented-pseudo-code">Implemented Pseudo Code</h4>
+<ul>
+<li><em>ImmutableAccess</em>: Drops setter, immutable</li>
+<li><em>Pointer</em> &amp; <em>ConstValue</em> &amp;
+<em>ConstElemCount</em>: Drops setter, native ownership on
+const-value</li>
+<li><em>Array</em> &amp; <em>ConstValue</em> : Drops setter, const-value
+array</li>
+<li><em>Primitive</em>
+<ul>
+<li>Single aggregated instance
+<ul>
+<li>Store value within <em>native</em> memory</li>
+</ul></li>
+<li><em>Array</em> | <em>Pointer</em>
+<ul>
+<li><em>MaxOneElement</em>
+<ul>
+<li><em>Pointer</em>
+<ul>
+<li><em>ConstValue</em>: Allocate new memory and store value</li>
+<li><em>VariaValue</em>:
+<ul>
+<li><em>ConstElemCount</em>: Reuse <em>native</em> memory and store
+value with matching <em>elemCount 1</em>, otherwise Exception</li>
+<li><em>VariaElemCount</em>: Reuse <em>native</em> memory and store
+value with matching <em>elemCount 1</em>, otherwise allocates new memory
+(had <em>elemCount 0</em>)</li>
+</ul></li>
+</ul></li>
+<li><em>Array</em> &amp; <em>VariaValue</em>: Reuse <em>native</em>
+memory and store value (has const <em>elemCount 1</em>)</li>
+<li><em>else</em>: <em>SKIP</em> setter for const single-primitive
+array</li>
+</ul></li>
+<li><em>AnyElementCount</em>
+<ul>
+<li><em>String</em> &amp; <em>isByteBuffer</em> &amp; <em>Pointer</em>
+<ul>
+<li><em>ConstElemCount</em>: Reuse <em>native</em> memory and store
+UTF-8 bytes with EOS with matching <em>elemCount</em>, otherwise
+Exception
+<ul>
+<li><em>StringOnly</em>: End, no more setter for this field, otherwise
+continue</li>
+</ul></li>
+<li><em>VariaElemCount</em>: Allocate new <em>native</em> memory and
+store UTF-8 bytes with EOS
+<ul>
+<li><em>StringOnly</em>: End, no more setter for this field, otherwise
+continue</li>
+</ul></li>
+</ul></li>
+<li><em>ConstValue</em>
+<ul>
+<li><em>Pointer</em>
+<ul>
+<li><em>VariaElemCount</em>: Allocates new <em>native</em> memory and
+store value</li>
+</ul></li>
+<li><em>else</em>: <em>SKIP</em> setter for const primitive array</li>
+</ul></li>
+<li><em>Array</em> | <em>ConstElemCount</em>: Reuse <em>native</em>
+memory and store value with &lt;= <em>elemCount</em>, otherwise
+Exception</li>
+<li><em>Pointer</em> &amp; <em>VariaElemCount</em>: Reuse
+<em>native</em> memory and store value with &lt;= <em>elemCount</em>,
+otherwise allocate new <em>native</em> memory</li>
+</ul></li>
+</ul></li>
+</ul></li>
+<li><em>Struct</em> ...</li>
+</ul>
<h3 id="struct-java-signature-table">Struct Java Signature Table</h3>
<p>Please find below signature table as generated by the <em>C
Declaration</em> including its <em>C Modifier</em>, e.g.
@@ -1569,79 +1686,97 @@ IndexOutOfBoundsException is thrown</li>
<li>this instance of chaining</li>
</ul></li>
</ul>
-<h3 id="struct-setter-pseudo-code">Struct Setter Pseudo-Code</h3>
-<ul>
-<li><em>ImmutableAccess</em>: Drops setter, immutable</li>
-<li><em>Pointer</em> &amp; <em>ConstValue</em> &amp;
-<em>ConstElemCount</em>: Drops setter, native ownership on
-const-value</li>
-<li><em>Array</em> &amp; <em>ConstValue</em> : Drops setter, const-value
-array</li>
-<li><em>Primitive</em>
-<ul>
-<li>Single aggregated instance
-<ul>
-<li>Store value within <em>native</em> memory</li>
-</ul></li>
-<li><em>Array</em> | <em>Pointer</em>
-<ul>
-<li><em>MaxOneElement</em>
-<ul>
-<li><em>Pointer</em>
-<ul>
-<li><em>ConstValue</em>: Allocate new memory and store value</li>
-<li><em>VariaValue</em>:
-<ul>
-<li><em>ConstElemCount</em>: Reuse <em>native</em> memory and store
-value with matching <em>elemCount 1</em>, otherwise Exception</li>
-<li><em>VariaElemCount</em>: Reuse <em>native</em> memory and store
-value with matching <em>elemCount 1</em>, otherwise allocates new memory
-(had <em>elemCount 0</em>)</li>
-</ul></li>
-</ul></li>
-<li><em>Array</em> &amp; <em>VariaValue</em>: Reuse <em>native</em>
-memory and store value (has const <em>elemCount 1</em>)</li>
-<li><em>else</em>: <em>SKIP</em> setter for const single-primitive
-array</li>
-</ul></li>
-<li><em>AnyElementCount</em>
-<ul>
-<li><em>String</em> &amp; <em>isByteBuffer</em> &amp; <em>Pointer</em>
-<ul>
-<li><em>ConstElemCount</em>: Reuse <em>native</em> memory and store
-UTF-8 bytes with EOS with matching <em>elemCount</em>, otherwise
-Exception
-<ul>
-<li><em>StringOnly</em>: End, no more setter for this field, otherwise
-continue</li>
-</ul></li>
-<li><em>VariaElemCount</em>: Allocate new <em>native</em> memory and
-store UTF-8 bytes with EOS
-<ul>
-<li><em>StringOnly</em>: End, no more setter for this field, otherwise
-continue</li>
-</ul></li>
-</ul></li>
-<li><em>ConstValue</em>
-<ul>
-<li><em>Pointer</em>
-<ul>
-<li><em>VariaElemCount</em>: Allocates new <em>native</em> memory and
-store value</li>
-</ul></li>
-<li><em>else</em>: <em>SKIP</em> setter for const primitive array</li>
-</ul></li>
-<li><em>Array</em> | <em>ConstElemCount</em>: Reuse <em>native</em>
-memory and store value with &lt;= <em>elemCount</em>, otherwise
-Exception</li>
-<li><em>Pointer</em> &amp; <em>VariaElemCount</em>: Reuse
-<em>native</em> memory and store value with &lt;= <em>elemCount</em>,
-otherwise allocate new <em>native</em> memory</li>
-</ul></li>
-</ul></li>
-</ul></li>
-<li><em>Struct</em> ...</li>
-</ul>
+<h3 id="struct-function-pointer-support">Struct Function Pointer
+Support</h3>
+<p>GlueGen supports function pointers as struct fields,<br />
+generating function calls as methods as well as
+<code>is&lt;FuncName&gt;Null()</code> checks<br />
+and function pointer opaque getter and setter as <code>long</code>
+types.</p>
+<h4 id="example">Example</h4>
+<p>Assume the following C Header file example:</p>
+<pre><code>typedef struct {
+ int32_t balance;
+} T2_UserData;
+
+typedef int32_t ( * T2_CustomFuncA)(void* aptr);
+
+typedef int32_t ( * T2_CustomFuncB)(T2_UserData* pUserData);
+
+typedef struct {
+ T2_CustomFuncA CustomFuncA1;
+ T2_CustomFuncB CustomFuncB1;
+} T2_InitializeOptions;</code></pre>
+<p>and the following GlueGen <em>no-magic</em> configuration</p>
+<pre><code>Opaque long void*
+
+EmitStruct T2_UserData
+StructPackage T2_UserData com.jogamp.gluegen.test.junit.generation
+
+EmitStruct T2_InitializeOptions
+StructPackage T2_InitializeOptions com.jogamp.gluegen.test.junit.generation</code></pre>
+<p>This will lead to the following result for
+<code>T2_InitializeOptions.customFuncA1</code></p>
+<pre><code> /** Interface to C language function: &lt;br&gt; &lt;code&gt;int32_t CustomFuncA1(void * aptr)&lt;/code&gt;&lt;br&gt; */
+ public final int CustomFuncA1(long aptr) { ... }
+
+ /**
+ * Returns `true` if native pointer &lt;code&gt;CustomFuncA1&lt;/code&gt; is `null`, otherwise `false`.
+ * &lt;p&gt;
+ * Corresponds to native field &lt;code&gt;CustomFuncA1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;/p&gt;
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncA&#39; -&gt; int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final boolean isCustomFuncA1Null() { .. }
+
+ /**
+ * Setter for native field &lt;code&gt;CustomFuncA1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncA&#39; -&gt; int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final T2_InitializeOptions setCustomFuncA1(long src) { .. }
+
+ /**
+ * Getter for native field &lt;code&gt;CustomFuncA1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncA&#39; -&gt; int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final long getCustomFuncA1() { .. } </code></pre>
+<p>and similar to <code>T2_InitializeOptions.customFuncB1</code></p>
+<pre><code> /** Interface to C language function: &lt;br&gt; &lt;code&gt;int32_t CustomFuncB1(T2_UserData * pUserData)&lt;/code&gt;&lt;br&gt; */
+ public final int CustomFuncB1(T2_UserData pUserData) { .. }
+
+ /**
+ * Returns `true` if native pointer &lt;code&gt;CustomFuncB1&lt;/code&gt; is `null`, otherwise `false`.
+ * &lt;p&gt;
+ * Corresponds to native field &lt;code&gt;CustomFuncB1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;/p&gt;
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncB&#39; -&gt; int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final boolean isCustomFuncB1Null() { .. }
+
+ /**
+ * Setter for native field &lt;code&gt;CustomFuncB1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncB&#39; -&gt; int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final T2_InitializeOptions setCustomFuncB1(long src) { .. }
+
+ /**
+ * Getter for native field &lt;code&gt;CustomFuncB1&lt;/code&gt;, being a &lt;i&gt;struct&lt;/i&gt; owned function pointer.
+ * &lt;p&gt;
+ * Native Field Signature &lt;code&gt;(PointerType) typedef &#39;T2_CustomFuncB&#39; -&gt; int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer&lt;/code&gt;
+ * &lt;/p&gt;
+ */
+ public final long getCustomFuncB1() { .. }
+</code></pre>
<h2 id="platform-header-files">Platform Header Files</h2>
<p>GlueGen provides convenient platform headers,<br />
which can be included in your C header files for native compilation and
diff --git a/doc/GlueGen_Mapping.md b/doc/GlueGen_Mapping.md
index 3105a66..9b562ee 100644
--- a/doc/GlueGen_Mapping.md
+++ b/doc/GlueGen_Mapping.md
@@ -537,8 +537,105 @@ A similar mapping is produced for `struct` types, i.e. *compounds*.
Returns:
* this instance of chaining
+### Struct Function Pointer Support
+GlueGen supports function pointers as struct fields,
+generating function calls as methods as well as `is<FuncName>Null()` checks
+and function pointer opaque getter and setter as `long` types.
+#### Example
+Assume the following C Header file example:
+```
+typedef struct {
+ int32_t balance;
+} T2_UserData;
+
+typedef int32_t ( * T2_CustomFuncA)(void* aptr);
+
+typedef int32_t ( * T2_CustomFuncB)(T2_UserData* pUserData);
+
+typedef struct {
+ T2_CustomFuncA CustomFuncA1;
+ T2_CustomFuncB CustomFuncB1;
+} T2_InitializeOptions;
+```
+
+and the following GlueGen *no-magic* configuration
+```
+Opaque long void*
+
+EmitStruct T2_UserData
+StructPackage T2_UserData com.jogamp.gluegen.test.junit.generation
+EmitStruct T2_InitializeOptions
+StructPackage T2_InitializeOptions com.jogamp.gluegen.test.junit.generation
+```
+
+This will lead to the following result for `T2_InitializeOptions.customFuncA1`
+```
+ /** Interface to C language function: <br> <code>int32_t CustomFuncA1(void * aptr)</code><br> */
+ public final int CustomFuncA1(long aptr) { ... }
+
+ /**
+ * Returns `true` if native pointer <code>CustomFuncA1</code> is `null`, otherwise `false`.
+ * <p>
+ * Corresponds to native field <code>CustomFuncA1</code>, being a <i>struct</i> owned function pointer.
+ * </p>
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncA' -> int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final boolean isCustomFuncA1Null() { .. }
+
+ /**
+ * Setter for native field <code>CustomFuncA1</code>, being a <i>struct</i> owned function pointer.
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncA' -> int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final T2_InitializeOptions setCustomFuncA1(long src) { .. }
+
+ /**
+ * Getter for native field <code>CustomFuncA1</code>, being a <i>struct</i> owned function pointer.
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncA' -> int32_t (*)(void * aptr), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final long getCustomFuncA1() { .. }
+```
+
+and similar to `T2_InitializeOptions.customFuncB1`
+```
+ /** Interface to C language function: <br> <code>int32_t CustomFuncB1(T2_UserData * pUserData)</code><br> */
+ public final int CustomFuncB1(T2_UserData pUserData) { .. }
+
+ /**
+ * Returns `true` if native pointer <code>CustomFuncB1</code> is `null`, otherwise `false`.
+ * <p>
+ * Corresponds to native field <code>CustomFuncB1</code>, being a <i>struct</i> owned function pointer.
+ * </p>
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncB' -> int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final boolean isCustomFuncB1Null() { .. }
+
+ /**
+ * Setter for native field <code>CustomFuncB1</code>, being a <i>struct</i> owned function pointer.
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncB' -> int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final T2_InitializeOptions setCustomFuncB1(long src) { .. }
+
+ /**
+ * Getter for native field <code>CustomFuncB1</code>, being a <i>struct</i> owned function pointer.
+ * <p>
+ * Native Field Signature <code>(PointerType) typedef 'T2_CustomFuncB' -> int32_t (*)(T2_UserData * pUserData), size [fixed false, lnx64 8], const[false], pointer*1, funcPointer</code>
+ * </p>
+ */
+ public final long getCustomFuncB1() { .. }
+
+```
## Platform Header Files
diff --git a/make/build-test.xml b/make/build-test.xml
index 6c4c3a1..a791c7c 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -703,16 +703,14 @@ chmod 644 ${results}/* \${line.separator}
</linker>
<patternset id="junit.test2.jnic.src.files">
- <include name="${build_t.gen.rootrel}/native/BindingtestT2Impl_JNI.c"/>
- <!-- include name="${build_t.gen.rootrel}/native/TK_Surface_JNI.c"/ -->
- <!-- include name="${build_t.gen.rootrel}/native/TK_ModelConst_JNI.c"/ -->
- <!-- include name="${build_t.gen.rootrel}/native/TK_ModelMutable_JNI.c"/ -->
+ <include name="${build_t.gen.rootrel}/native/Bindingtest2Impl_JNI.c"/>
+ <include name="${build_t.gen.rootrel}/native/T2_InitializeOptions_JNI.c"/>
</patternset>
<c.build c.compiler.src.files="junit.test2.jnic.src.files"
output.lib.name="Bindingtest2"
compiler.cfg.id="${compiler.cfg.id}"
- linker.cfg.id="linker.test1.runtime.cfg.id"/>
+ linker.cfg.id="linker.test2.runtime.cfg.id"/>
</target>
diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index 4f40cd6..ff33853 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -148,10 +148,11 @@ function onetest() {
#onetest com.jogamp.gluegen.jcpp.TokenPastingWhitespaceTest 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.jcpp.PreprocessorTest 2>&1 | tee -a $LOG
-onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
+#onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2LoadJNIAndImplLib 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2DynamicLibraryBundle 2>&1 | tee -a $LOG
+onetest com.jogamp.gluegen.test.junit.generation.Test2 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.structgen.TestStructGen01 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.structgen.TestStructGen02 2>&1 | tee -a $LOG
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index c425c05..23aae96 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -965,10 +965,11 @@ public class JavaEmitter implements GlueEmitter {
final String fieldName = null==renamed ? field.getName() : renamed;
final String cfgFieldName1 = JavaConfiguration.canonicalStructFieldSymbol(containingJTypeName, fieldName);
if (fieldType.isFunctionPointer()) {
- // no offset/size for function pointer ..
if( GlueGen.debug() ) {
- System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.getDebugString(), "SKIP FuncPtr");
+ System.err.printf("SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.getDebugString(), "FuncPtr");
}
+ generateOffsetAndSizeArrays(javaUnit, " ", fieldName, null, field, null); /* w/o size */
+ generateOffsetAndSizeArrays(javaUnit, "//", fieldName, fieldType, null, null);
} else if (fieldType.isCompound()) {
// FIXME: will need to support this at least in order to
// handle the union in jawt_Win32DrawingSurfaceInfo (fabricate
@@ -1099,6 +1100,28 @@ public class JavaEmitter implements GlueEmitter {
func.rename(renamed); // null is OK
generateFunctionPointerCode(methodBindingSet, javaUnit, jniUnit, structCTypeName,
containingCType, containingJType, i, func, fqStructFieldName1);
+ final String javaTypeName = "long";
+ final String capFieldName = capitalizeString(fieldName);
+ generateIsNullSignature(javaUnit, false, fieldName, fieldType, Ownership.Parent, capFieldName, false, false, null);
+ javaUnit.emitln(" {");
+ javaUnit.emitln(" return 0 == accessor.getLongAt(" + fieldName+"_offset[mdIdx], md.pointerSizeInBytes());");
+ javaUnit.emitln(" }");
+ javaUnit.emitln();
+ if( !immutableField && !fieldType.isConst() ) {
+ // Setter
+ generateSetterSignature(javaUnit, MethodAccess.PUBLIC, false, false, fieldName, fieldType, Ownership.Parent, containingJTypeName, capFieldName, null, javaTypeName, null, false, false, null, null, null);
+ javaUnit.emitln(" {");
+ javaUnit.emitln(" accessor.setLongAt(" + fieldName+"_offset[mdIdx], src, md.pointerSizeInBytes());");
+ javaUnit.emitln(" return this;");
+ javaUnit.emitln(" }");
+ javaUnit.emitln();
+ }
+ // Getter
+ generateGetterSignature(javaUnit, false, false, fieldName, fieldType, Ownership.Parent, javaTypeName, capFieldName, null, false, false, null, null);
+ javaUnit.emitln(" {");
+ javaUnit.emitln(" return accessor.getLongAt(" + fieldName+"_offset[mdIdx], md.pointerSizeInBytes());");
+ javaUnit.emitln(" }");
+ javaUnit.emitln();
} else if ( fieldType.isCompound() && !isOpaqueField ) {
// FIXME: will need to support this at least in order to
// handle the union in jawt_Win32DrawingSurfaceInfo (fabricate a name?)
@@ -1223,16 +1246,26 @@ public class JavaEmitter implements GlueEmitter {
final String fieldName, final Type fieldType, final Ownership ownership,
final boolean constElemCount, final boolean maxOneElem, final String elemCountExpr,
final boolean multiline, final boolean startNewPara) {
- final boolean isPointer;
+ final boolean isArray;
final Type referencedType;
+ final String relationship;
{
- final PointerType pointerType = fieldType.asPointer();
- if( null != pointerType ) {
- isPointer = true;
- referencedType = pointerType.getBaseType();
+ if( fieldType.isFunctionPointer() ) {
+ isArray = false;
+ referencedType = null;
+ relationship = "being";
+ } else if( fieldType.pointerDepth() > 0 ) {
+ isArray = true;
+ referencedType = fieldType.getBaseType();
+ relationship = "referencing";
+ } else if( fieldType.arrayDimension() > 0 ) {
+ isArray = true;
+ referencedType = null;
+ relationship = "being";
} else {
- isPointer = false;
+ isArray = false;
referencedType = null;
+ relationship = "being";
}
}
// isPointer = true;
@@ -1247,24 +1280,35 @@ public class JavaEmitter implements GlueEmitter {
}
final String ownershipTerm;
switch( ownership ) {
- case Parent: ownershipTerm = "an"; break;
+ case Parent: ownershipTerm = "a <i>struct</i> owned"; break;
case Java: ownershipTerm = "a <i>Java</i> owned"; break;
case Native: ownershipTerm = "a <i>natively</i> owned"; break;
default: ownershipTerm = "a <i>mixed and ambigously</i> owned (<b>warning</b>)"; break;
}
- final String relationship = isPointer ? "referencing" : "being";
-
- unit.emit("native field <code>"+fieldName+"</code>, "+relationship+" "+ownershipTerm+" array with "+(constElemCount?"fixed":"variable")+" element count");
- if( null != elemCountExpr ) {
- if( elemCountExpr.startsWith("get") && elemCountExpr.endsWith("()") ) {
- unit.emit(" of {@link #"+elemCountExpr+"} ");
- } else {
- unit.emit(" of <code>"+elemCountExpr+"</code> ");
- }
- if( constElemCount || Ownership.Mixed == ownership ) {
- unit.emit("elements.");
+ final String what;
+ if( fieldType.isFunctionPointer() ) {
+ what = "function pointer";
+ } else if( isArray ) {
+ what = "array";
+ } else {
+ what = fieldType.getClass().getSimpleName();
+ }
+ unit.emit("native field <code>"+fieldName+"</code>, "+relationship+" "+ownershipTerm+" "+what);
+ if( isArray ) {
+ unit.emit(" with "+(constElemCount?"fixed":"variable")+" element count");
+ if( null != elemCountExpr ) {
+ if( elemCountExpr.startsWith("get") && elemCountExpr.endsWith("()") ) {
+ unit.emit(" of {@link #"+elemCountExpr+"} ");
+ } else {
+ unit.emit(" of <code>"+elemCountExpr+"</code> ");
+ }
+ if( constElemCount || Ownership.Mixed == ownership ) {
+ unit.emit("elements.");
+ } else {
+ unit.emit("initial elements.");
+ }
} else {
- unit.emit("initial elements.");
+ unit.emit(".");
}
} else {
unit.emit(".");
@@ -1437,6 +1481,7 @@ public class JavaEmitter implements GlueEmitter {
false, // isPrivateNativeMethod
cfg);
emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
+ emitter.addModifier(JavaMethodBindingEmitter.FINAL);
emitter.emit();
javaUnit.emitln();
@@ -1572,17 +1617,17 @@ public class JavaEmitter implements GlueEmitter {
final JavaType containingJType,
final int i, final Field field, final String fieldName,
final boolean immutableAccess,
- final String returnSizeLookupName) throws Exception {
+ final String fqStructFieldName) throws Exception {
final Type fieldType = field.getType();
final JavaType javaType;
try {
javaType = typeToJavaType(fieldType, machDescJava);
} catch (final Exception e) {
throw new GlueGenException("Error occurred while creating array/pointer accessor for field \"" +
- returnSizeLookupName + "\", "+fieldType.getDebugString(), fieldType.getASTLocusTag(), e);
+ fqStructFieldName + "\", "+fieldType.getDebugString(), fieldType.getASTLocusTag(), e);
}
if( GlueGen.debug() ) {
- System.err.printf("SE.ac.%02d: fieldName %s%n", (i+1), fieldName);
+ System.err.printf("SE.ac.%02d: fieldName %s, fqName %s%n", (i+1), fieldName, fqStructFieldName);
System.err.printf("SE.ac.%02d: structCType %s, %s%n", (i+1), structCType.toString(), structCType.getSignature(null).toString());
System.err.printf("SE.ac.%02d: fieldType %s, %s%n", (i+1), fieldType.toString(), fieldType.getSignature(null).toString());
System.err.printf("SE.ac.%02d: javaType %s, %s%n", (i+1), javaType.toString(), javaType.getSignature(null).toString());
@@ -1593,8 +1638,8 @@ public class JavaEmitter implements GlueEmitter {
//
final String containingJTypeName = containingJType.getName();
final boolean isOpaque = isOpaque(fieldType);
- final boolean isStringOnly = cfg.returnsStringOnly(returnSizeLookupName); // exclude alternative ByteBuffer representation to String
- final boolean isString = isStringOnly || cfg.returnsString(returnSizeLookupName);
+ final boolean isStringOnly = cfg.returnsStringOnly(fqStructFieldName); // exclude alternative ByteBuffer representation to String
+ final boolean isString = isStringOnly || cfg.returnsString(fqStructFieldName);
if( isString ) {
unit.addTailCode(optStringCharsetCode);
}
@@ -1634,7 +1679,7 @@ public class JavaEmitter implements GlueEmitter {
if( null != arrayType ) {
final int[][] arrayLengthRes = new int[1][];
final boolean[] _useFixedArrayLen = { false };
- elemCountExpr = getArrayArrayLengthExpr(arrayType, returnSizeLookupName, _useFixedArrayLen, arrayLengthRes);
+ elemCountExpr = getArrayArrayLengthExpr(arrayType, fqStructFieldName, _useFixedArrayLen, arrayLengthRes);
// final int arrayLength = arrayLengthRes[0][0];
constElemCount = _useFixedArrayLen[0];
ownership = Ownership.Parent; // a fixed linear array
@@ -1644,11 +1689,11 @@ public class JavaEmitter implements GlueEmitter {
useGetCStringLength = false;
} else {
final PointerType pointerType = fieldType.asPointer();
- final String _elemCountExpr = cfg.returnedArrayLength(returnSizeLookupName);
+ final String _elemCountExpr = cfg.returnedArrayLength(fqStructFieldName);
baseCElemType = pointerType.getBaseType();
isPointer = true;
if( 1 != pointerType.pointerDepth() ) {
- final String msg = "SKIP ptr-ptr (depth "+pointerType.pointerDepth()+"): "+returnSizeLookupName +": "+fieldType;
+ final String msg = "SKIP ptr-ptr (depth "+pointerType.pointerDepth()+"): "+fqStructFieldName +": "+fieldType;
unit.emitln(" // "+msg);
unit.emitln();
LOG.log(WARNING, structCType.getASTLocusTag(), msg);
@@ -1702,13 +1747,13 @@ public class JavaEmitter implements GlueEmitter {
}
}
if( null == elemCountExpr ) {
- final String msg = "SKIP unsized array in struct: "+returnSizeLookupName+": "+fieldType.getSignature(null).toString();
+ final String msg = "SKIP unsized array in struct: "+fqStructFieldName+": "+fieldType.getSignature(null).toString();
unit.emitln(" // "+msg);
unit.emitln();
LOG.log(WARNING, structCType.getASTLocusTag(), msg);
return;
}
- boolean _maxOneElement = cfg.maxOneElement(returnSizeLookupName);
+ boolean _maxOneElement = cfg.maxOneElement(fqStructFieldName);
if( !_maxOneElement ) {
try {
_maxOneElement = 1 == Integer.parseInt(elemCountExpr);
@@ -1720,7 +1765,7 @@ public class JavaEmitter implements GlueEmitter {
}
if( !baseCElemType.hasSize() ) { // like 'void*' -> 'void'
- final String msg = "SKIP unsized field in struct: "+returnSizeLookupName+": fieldType "+fieldType.getSignature(null).toString()+", baseType "+baseCElemType.getSignature(null).toString();
+ final String msg = "SKIP unsized field in struct: "+fqStructFieldName+": fieldType "+fieldType.getSignature(null).toString()+", baseType "+baseCElemType.getSignature(null).toString();
unit.emitln(" // "+msg);
unit.emitln();
LOG.log(WARNING, structCType.getASTLocusTag(), msg);
@@ -1733,7 +1778,7 @@ public class JavaEmitter implements GlueEmitter {
baseJElemType = typeToJavaType(baseCElemType, machDescJava);
} catch (final Exception e ) {
throw new GlueGenException("Error occurred while creating array/pointer accessor for field \"" +
- returnSizeLookupName + "\", baseType "+baseCElemType.getDebugString()+", topType "+fieldType.getDebugString(),
+ fqStructFieldName + "\", baseType "+baseCElemType.getDebugString()+", topType "+fieldType.getDebugString(),
fieldType.getASTLocusTag(), e);
}
baseJElemTypeName = baseJElemType.getName();
@@ -1874,7 +1919,7 @@ public class JavaEmitter implements GlueEmitter {
if( isConstValue ) {
// constElemCount/Ownership.Native excluded: SKIP setter for constValue constElemCount Pointer w/ native ownership
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", 1);");
@@ -1971,7 +2016,7 @@ public class JavaEmitter implements GlueEmitter {
generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, null,
baseJElemTypeName+"[]", SetReplaceArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetReplaceArrayApiDocDetail, SetReplaceArrayApiDocArgs);
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(SetReplaceArrayArgsCheck);
@@ -2010,7 +2055,7 @@ public class JavaEmitter implements GlueEmitter {
generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, SetArrayArgsPre,
baseJElemTypeName+"[]", SetArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetArrayApiDocDetail, SetArrayApiDocArgs);
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(SetArrayArgsCheck);
@@ -2060,7 +2105,7 @@ public class JavaEmitter implements GlueEmitter {
if( isConstValue ) {
// constElemCount/Ownership.Native excluded: SKIP setter for constValue constElemCount Pointer w/ native ownership
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+".size(), 1);");
@@ -2112,7 +2157,7 @@ public class JavaEmitter implements GlueEmitter {
generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, null,
baseJElemTypeName+"[]", SetReplaceArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetReplaceArrayApiDocDetail, SetReplaceArrayApiDocArgs);
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(SetReplaceArrayArgsCheck);
@@ -2147,7 +2192,7 @@ public class JavaEmitter implements GlueEmitter {
generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, SetArrayArgsPre,
baseJElemTypeName+"[]", SetArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetArrayApiDocDetail, SetArrayApiDocArgs);
if( Ownership.Native == ownership ) {
- throw new InternalError("Native ownership but adding potential memory-replacement for '"+returnSizeLookupName+"': "+fieldType.getSignature(null).toString());
+ throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString());
}
unit.emitln(" {");
unit.emitln(SetArrayArgsCheck);
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
index 6b841ad..67f4918 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
@@ -54,6 +54,16 @@ public class BindingJNILibLoader extends JNILibLoaderBase {
}
});
}
+
+ public static void loadBindingtest2() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ loadLibrary("Bindingtest2", null, true, BindingJNILibLoader.class.getClassLoader());
+ return null;
+ }
+ });
+ }
}
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test2.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test2.java
new file mode 100644
index 0000000..636eea7
--- /dev/null
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test2.java
@@ -0,0 +1,148 @@
+/**
+ * Copyright 2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.gluegen.test.junit.generation;
+
+import java.io.IOException;
+
+import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest2Impl;
+import com.jogamp.common.os.NativeLibrary;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test {@link Bindingtest2} with {@link T2_InitializeOptions} instance and function pointer...
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class Test2 extends BaseClass {
+
+ static NativeLibrary dynamicLookupHelper;
+
+ /**
+ * Verifies loading of the new library.
+ */
+ @BeforeClass
+ public static void chapter__TestLoadLibrary() throws Exception {
+ BindingJNILibLoader.loadBindingtest2();
+ dynamicLookupHelper = NativeLibrary.open("test2", false, false, Test2.class.getClassLoader(), true);
+ Assert.assertNotNull("NativeLibrary.open(test2) failed", dynamicLookupHelper);
+
+ Bindingtest2Impl.resetProcAddressTable(dynamicLookupHelper);
+ }
+
+ /**
+ * Verifies unloading of the new library.
+ */
+ @AfterClass
+ public static void chapter0XTestUnloadLibrary() throws Exception {
+ Assert.assertNotNull(dynamicLookupHelper);
+ dynamicLookupHelper.close();
+ dynamicLookupHelper = null;
+ }
+
+ /**
+ * Test Bindingtest2 with T2_InitializeOptions instance and function pointer
+ */
+ @Test
+ public void chapter01() throws Exception {
+ final Bindingtest2 bt2 = new Bindingtest2Impl();
+
+ final T2_InitializeOptions options = T2_InitializeOptions.create();
+ Assert.assertEquals(true, options.isOverrideThreadAffinityNull());
+ Assert.assertEquals(true, options.isProductNameNull());
+ Assert.assertEquals(true, options.isProductVersionNull());
+ Assert.assertEquals(true, options.isCustomFuncA1Null());
+ Assert.assertEquals(true, options.isCustomFuncA2Null());
+ Assert.assertEquals(true, options.isCustomFuncB1Null());
+ Assert.assertEquals(true, options.isCustomFuncB2Null());
+
+ bt2.Initialize(options);
+ Assert.assertEquals(true, options.isOverrideThreadAffinityNull());
+ Assert.assertEquals(false, options.isProductNameNull());
+ Assert.assertEquals(false, options.isProductVersionNull());
+ Assert.assertEquals(false, options.isCustomFuncA1Null());
+ Assert.assertEquals(false, options.isCustomFuncA2Null());
+ Assert.assertEquals(false, options.isCustomFuncB1Null());
+ Assert.assertEquals(false, options.isCustomFuncB2Null());
+ Assert.assertEquals(false, options.isCustomFuncA1Null());
+ Assert.assertEquals(1, options.getApiVersion());
+ Assert.assertEquals("Product Name", options.getProductName());
+ Assert.assertEquals("Product Version", options.getProductVersion());
+ Assert.assertEquals(0xa001, options.CustomFuncA1(0));
+ Assert.assertEquals(0xa002, options.CustomFuncA2(0));
+ final T2_UserData ud1 = T2_UserData.create();
+ {
+ ud1.setBalance(101);
+ ud1.setName("John Doe");
+ Assert.assertEquals(101, ud1.getBalance());
+ Assert.assertEquals("John Doe", ud1.getName());
+ }
+ final T2_UserData ud2 = T2_UserData.create();
+ {
+ ud2.setBalance(404);
+ ud2.setName("Jane Doe");
+ Assert.assertEquals(404, ud2.getBalance());
+ Assert.assertEquals("Jane Doe", ud2.getName());
+ }
+ Assert.assertEquals(101, options.CustomFuncB1(ud1));
+ Assert.assertEquals(404, options.CustomFuncB1(ud2));
+ Assert.assertEquals(-101, options.CustomFuncB2(ud1));
+ Assert.assertEquals(-404, options.CustomFuncB2(ud2));
+ // switch functions
+ {
+ final long funcB1 = options.getCustomFuncB1();
+ final long funcB2 = options.getCustomFuncB2();
+ options.setCustomFuncB1(funcB2);
+ options.setCustomFuncB2(funcB1);
+ }
+ Assert.assertEquals(-101, options.CustomFuncB1(ud1));
+ Assert.assertEquals(-404, options.CustomFuncB1(ud2));
+ Assert.assertEquals(101, options.CustomFuncB2(ud1));
+ Assert.assertEquals(404, options.CustomFuncB2(ud2));
+
+ bt2.Release(options);
+ Assert.assertEquals(true, options.isOverrideThreadAffinityNull());
+ Assert.assertEquals(true, options.isProductNameNull());
+ Assert.assertEquals(true, options.isProductVersionNull());
+ Assert.assertEquals(true, options.isCustomFuncA1Null());
+ Assert.assertEquals(true, options.isCustomFuncA2Null());
+ Assert.assertEquals(true, options.isCustomFuncB1Null());
+ Assert.assertEquals(true, options.isCustomFuncB2Null());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = Test2.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
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 3fff02c..561b3ae 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c
@@ -1,20 +1,55 @@
#include "test2.h"
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-int Initialize(const T2_InitializeOptions* Options) {
- fprintf(stderr, "T2 Initialize API 0x%X, product %s, version %s\n",
- Options->ApiVersion,
- Options->ProductName,
- Options->ProductVersion);
- fprintf(stderr, "- MemFuncs: alloc %p, realloc %p, release %p\n",
- Options->AllocateMemoryFunction,
- Options->ReallocateMemoryFunction,
- Options->ReleaseMemoryFunction);
- return 0;
+static int32_t CustomFuncA1(void* aptr) {
+ (void)aptr;
+ return 0xa001;
+}
+static int32_t CustomFuncA2(void* aptr) {
+ (void)aptr;
+ return 0xa002;
+}
+
+static int32_t CustomFuncB1(T2_UserData* pUserData) {
+ return pUserData->balance;
}
-int Shutdown() {
- return 0;
+static int32_t CustomFuncB2(T2_UserData* pUserData) {
+ return -pUserData->balance;
}
+int Initialize(T2_InitializeOptions* Options) {
+ Options->ProductName = calloc(100, sizeof(char));
+ Options->ProductVersion = calloc(100, sizeof(char));
+ strncpy(Options->ProductName, "Product Name", 100);
+ strncpy(Options->ProductVersion, "Product Version", 100);
+ Options->ApiVersion = 1;
+
+ Options->Reserved1 = NULL;
+ Options->CustomFuncA1 = CustomFuncA1;
+ Options->CustomFuncA2 = CustomFuncA2;
+ Options->CustomFuncB1 = CustomFuncB1;
+ Options->CustomFuncB2 = CustomFuncB2;
+
+ Options->OverrideThreadAffinity = NULL;
+}
+
+int Release(T2_InitializeOptions* Options) {
+ if( NULL != Options->ProductName ) {
+ free( Options->ProductName );
+ Options->ProductName = NULL;
+ }
+ if( NULL != Options->ProductVersion ) {
+ free( Options->ProductVersion );
+ Options->ProductVersion = NULL;
+ }
+ Options->CustomFuncA1 = NULL;
+ Options->CustomFuncA2 = NULL;
+ Options->CustomFuncB1 = NULL;
+ Options->CustomFuncB2 = NULL;
+}
+
+
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 b55e1d6..4ca9ae5 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg
@@ -1,12 +1,12 @@
Package com.jogamp.gluegen.test.junit.generation
-JavaClass BindingtestT2
+JavaClass Bindingtest2
Style InterfaceAndImpl
JavaOutputDir classes
NativeOutputDir native
# Use a ProcAddressTable so we dynamically look up the routines
EmitProcAddressTable true
-ProcAddressTableClassName BindingtestT2ProcAddressTable
+ProcAddressTableClassName Bindingtest2ProcAddressTable
GetProcAddressTableExpr _table
ProcAddressNameExpr PFN $UPPERCASE({0}) PROC
@@ -19,36 +19,32 @@ ForceProcAddressGen __ALL__
# pointer typedefs for these routines to MYAPIENTRY
# LocalProcAddressCallingConvention __ALL__ MYAPIENTRY
-Opaque long T2_AllocateMemoryFunc
-Opaque long T2_ReallocateMemoryFunc
-Opaque long T2_ReleaseMemoryFunc
+Opaque long void*
EmitStruct T2_ThreadAffinity
StructPackage T2_ThreadAffinity com.jogamp.gluegen.test.junit.generation
+EmitStruct T2_UserData
+StructPackage T2_UserData com.jogamp.gluegen.test.junit.generation
+ReturnsStringOnly T2_UserData.name
+
EmitStruct T2_InitializeOptions
StructPackage T2_InitializeOptions com.jogamp.gluegen.test.junit.generation
ReturnsStringOnly T2_InitializeOptions.ProductName
ReturnsStringOnly T2_InitializeOptions.ProductVersion
-Opaque long T2_InitializeOptions.Reserved2
-# ImmutableAccess long T2_InitializeOptions.Reserved
-
# ReturnedArrayLength T2_InitializeOptions.OverrideThreadAffinity 1
MaxOneElement T2_InitializeOptions.OverrideThreadAffinity
-ReturnsOpaque long T2_InitializeOptions.AllocateMemoryFunction
-ReturnsOpaque long T2_InitializeOptions.ReallocateMemoryFunc
-ReturnsOpaque long T2_InitializeOptions.ReleaseMemoryFunc
-
CustomCCode #include "test2.h"
-Import com.jogamp.gluegen.test.junit.generation.BindingtestT2
+Import com.jogamp.gluegen.test.junit.generation.Bindingtest2
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
-CustomJavaCode BindingtestT2Impl private static BindingtestT2ProcAddressTable _table = new BindingtestT2ProcAddressTable();
-CustomJavaCode BindingtestT2Impl public static void resetProcAddressTable(DynamicLookupHelper lookup) {
-CustomJavaCode BindingtestT2Impl _table.reset(lookup);
-CustomJavaCode BindingtestT2Impl }
+CustomJavaCode Bindingtest2Impl private static Bindingtest2ProcAddressTable _table = new Bindingtest2ProcAddressTable();
+CustomJavaCode Bindingtest2Impl public static void resetProcAddressTable(DynamicLookupHelper lookup) {
+CustomJavaCode Bindingtest2Impl _table.reset(lookup);
+CustomJavaCode Bindingtest2Impl }
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 58b5c8f..0fca16a 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h
@@ -2,14 +2,6 @@
#include <gluegen_stdint.h>
#include <gluegen_stddef.h>
-typedef void* ( * T2_AllocateMemoryFunc)(size_t SizeInBytes, size_t Alignment);
-
-typedef void* ( * T2_ReallocateMemoryFunc)(void* Pointer, size_t SizeInBytes, size_t Alignment);
-
-typedef void ( * T2_ReleaseMemoryFunc)(void* Pointer);
-
-typedef void ( * T2_CustomFunc)(void* Pointer);
-
typedef struct {
int32_t ApiVersion;
uint64_t NetworkWork;
@@ -21,21 +13,28 @@ typedef struct {
} T2_ThreadAffinity;
typedef struct {
- int32_t ApiVersion;
- T2_AllocateMemoryFunc AllocateMemoryFunction;
- T2_ReallocateMemoryFunc ReallocateMemoryFunction;
- T2_ReleaseMemoryFunc ReleaseMemoryFunction;
-
+ int32_t balance;
+ const char* name;
+} T2_UserData;
+
+typedef int32_t ( * T2_CustomFuncA)(void* aptr);
+
+typedef int32_t ( * T2_CustomFuncB)(T2_UserData* pUserData);
+
+typedef struct {
const char* ProductName;
-
const char* ProductVersion;
+ int32_t ApiVersion;
+
void* Reserved1;
- void* Reserved2;
- T2_CustomFunc CustomFunc2;
+ T2_CustomFuncA CustomFuncA1;
+ T2_CustomFuncA CustomFuncA2;
+ T2_CustomFuncB CustomFuncB1;
+ T2_CustomFuncB CustomFuncB2;
T2_ThreadAffinity* OverrideThreadAffinity;
} T2_InitializeOptions;
-extern int Initialize(const T2_InitializeOptions* Options);
-extern int Shutdown();
+extern int Initialize(T2_InitializeOptions* Options);
+extern int Release(T2_InitializeOptions* Options);