diff options
author | Sven Gothel <[email protected]> | 2023-06-20 04:02:12 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-06-20 04:02:12 +0200 |
commit | b9dc722d689760bf85628edd8766dc6cd2360c8e (patch) | |
tree | 2d94b694cbc39b81f55ce1533da1f8d32e86ccaf | |
parent | f7f554208c024280f1929df79bdbb83c758b8b49 (diff) |
GlueGen Struct [15]: Add FunctionPointer getter and setter support w/ documentation
-rw-r--r-- | doc/GlueGen_Mapping.html | 285 | ||||
-rw-r--r-- | doc/GlueGen_Mapping.md | 97 | ||||
-rw-r--r-- | make/build-test.xml | 8 | ||||
-rwxr-xr-x | make/scripts/runtest.sh | 3 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaEmitter.java | 123 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java | 10 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/Test2.java | 148 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.c | 59 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg | 30 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.h | 35 |
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> & <em>ConstValue</em> & +<em>ConstElemCount</em>: Drops setter, native ownership on +const-value</li> +<li><em>Array</em> & <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> & <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> & <em>isByteBuffer</em> & <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 <= <em>elemCount</em>, otherwise +Exception</li> +<li><em>Pointer</em> & <em>VariaElemCount</em>: Reuse +<em>native</em> memory and store value with <= <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> & <em>ConstValue</em> & -<em>ConstElemCount</em>: Drops setter, native ownership on -const-value</li> -<li><em>Array</em> & <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> & <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> & <em>isByteBuffer</em> & <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 <= <em>elemCount</em>, otherwise -Exception</li> -<li><em>Pointer</em> & <em>VariaElemCount</em>: Reuse -<em>native</em> memory and store value with <= <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<FuncName>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: <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() { .. } </code></pre> +<p>and similar to <code>T2_InitializeOptions.customFuncB1</code></p> +<pre><code> /** 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() { .. } +</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); |