diff options
author | Sven Gothel <[email protected]> | 2023-06-23 07:09:24 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-06-23 07:09:24 +0200 |
commit | 23f4c6347ea24cf619dba573e83790e73d81d5ad (patch) | |
tree | 104fadd83f6c9718b15428e9eb2ed2f8554f4ba4 | |
parent | 829d69ca42d2022790b136a5f689c34919a7c775 (diff) |
GlueGen Struct [16]: Add support for pointer-pointer and function-pointer values
See documentation and unit test test2.h, Test2FuncPtr.java and Test3PtrStorage.java
-rw-r--r-- | doc/GlueGen_Mapping.html | 93 | ||||
-rw-r--r-- | doc/GlueGen_Mapping.md | 86 | ||||
-rwxr-xr-x | make/scripts/runtest.sh | 3 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaEmitter.java | 368 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/Test2FuncPtr.java | 16 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/Test3PtrStorage.java | 139 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.c | 38 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg | 9 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.h | 43 |
9 files changed, 592 insertions, 203 deletions
diff --git a/doc/GlueGen_Mapping.html b/doc/GlueGen_Mapping.html index 69aa11f..dd63718 100644 --- a/doc/GlueGen_Mapping.html +++ b/doc/GlueGen_Mapping.html @@ -421,6 +421,7 @@ <li><a href="#overview">Overview</a></li> <li><a href="#primitive-mapping">Primitive Mapping</a> <ul> + <li><a href="#pointer-mapping">Pointer Mapping</a></li> <li><a href="#string-mapping">String Mapping</a></li> <li><a href="#alignment-for-compound-data">Alignment for Compound Data</a></li> @@ -436,8 +437,12 @@ Table</a></li> <li><a href="#struct-java-signature-examples">Struct Java Signature Examples</a></li> - <li><a href="#struct-function-pointer-support">Struct Function Pointer + <li><a href="#struct-pointer-pointer-support">Struct Pointer-Pointer Support</a></li> + <li><a href="#struct-function-pointer-support">Struct Function-Pointer + Support</a></li> + <li><a href="#java-callback-from-native-c-api-support">Java Callback + from Native C-API 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> @@ -730,6 +735,15 @@ since we don't differentiate the OS and it's bit size is ambiguous.</li> to <em>PointerBuffer</em>, to reflect the architecture depending storage size.</li> </ul> +<h3 id="pointer-mapping">Pointer Mapping</h3> +<p><em>Pointer</em> values itself are represented as <code>long</code> +values on the Java side while using the native pointer-size, e.g. 32-bit +or 64-bit, on the native end.</p> +<p>They may simply be accessible via <code>long</code> or +<code>long[]</code> primitives in Java, or are exposed via +<code>com.jogamp.common.nio.PointerBuffer</code>.</p> +<p>See <a href="#struct-pointer-pointer-support">Struct Pointer-Pointer +Support</a> below.</p> <h3 id="string-mapping">String Mapping</h3> <h4 id="function-return-string-values">Function return String values</h4> @@ -926,20 +940,28 @@ fields</p> <ul> <li>See <a href="#primitive-mapping"><em>Primitive Mapping</em></a> above.</li> +<li>See <a href="#pointer-mapping"><em>Pointer Mapping</em></a> for +<em>pointer-to-pointer</em> values above and <a +href="#struct-pointer-pointer-support">Struct Pointer-Pointer +Support</a> below.</li> <li>See <a href="#string-mapping"><em>String Mapping</em></a> above.</li> </ul></li> -<li><em>Struct</em>, i.e. another compound variable</li> +<li><em>Struct</em>, i.e. an aggregated or referenced compound +variable</li> <li><em>Function Pointer</em>, a <em>typedef</em>'ed and set callable -function pointer</li> +function pointer, see <a href="#struct-function-pointer-support">Struct +Function-Pointer Support</a> below.</li> +<li><em>Java Callback from Native Code</em>, see <a +href="#java-callback-from-native-c-api-support">section below</a></li> </ul> <p>A field may be a direct aggregation, i.e. instance, within the struct including an array or a reference to a single element or array via a pointer.</p> -<p>Both, <em>primitive</em> and <em>struct</em> field type mappings only -produce pure Java code, utilizing the <em>GlueGen Runtime</em>. Hence no -additional native code must be compiled nor a resulting additional -library loaded to use the mapping.</p> +<p>Both, <em>primitive</em>, <em>struct</em> and <em>pointer</em> field +type mappings only produce pure Java code, utilizing the <em>GlueGen +Runtime</em>. Hence no additional native code must be compiled nor a +resulting additional library loaded to use the mapping.</p> <p>Only when mapping <em>function-pointer</em> within <em>structs</em>, additional native glue-code is produced to call the underlying native function which has to be compiled and its library loaded.</p> @@ -1686,7 +1708,33 @@ IndexOutOfBoundsException is thrown</li> <li>this instance of chaining</li> </ul></li> </ul> -<h3 id="struct-function-pointer-support">Struct Function Pointer +<h3 id="struct-pointer-pointer-support">Struct Pointer-Pointer +Support</h3> +<p>See primitive <a href="#pointer-mapping"><em>Pointer Mapping</em></a> +above.</p> +<p><em>Pointer</em> are exposed in the following examples</p> +<pre><code>typedef struct { + int32_t* int32PtrArray[10]; + int32_t** int32PtrPtr; + + ... +} T2_PointerStorage;</code></pre> +<p>or via and undefined forward-declared struct</p> +<pre><code>typedef struct T2_UndefStruct* T2_UndefStructPtr; + +typedef struct { + ... + + T2_UndefStructPtr undefStructPtr; + T2_UndefStructPtr undefStructPtrArray[10]; + T2_UndefStructPtr* undefStructPtrPtr; + const T2_UndefStructPtr* constUndefStructPtrPtr; +} T2_PointerStorage;</code></pre> +<p>and the following GlueGen configuration</p> +<pre><code>Opaque long T2_UndefStruct* +Ignore T2_UndefStruct</code></pre> +<p><em>TODO: Enhance documentation</em></p> +<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 function-pointer opaque @@ -1703,10 +1751,22 @@ typedef int32_t ( * T2_CustomFuncA)(void* aptr); typedef int32_t ( * T2_CustomFuncB)(T2_UserData* pUserData); typedef struct { - const T2_CustomFuncA CustomFuncA1; - T2_CustomFuncB CustomFuncB1; + ... + + T2_CustomFuncA customFuncAVariantsArray[10]; + T2_CustomFuncA* customFuncAVariantsArrayPtr; + + T2_CustomFuncB customFuncBVariantsArray[10]; + T2_CustomFuncB* customFuncBVariantsArrayPtr; +} T2_PointerStorage; + +typedef struct { + ... + + const T2_CustomFuncA CustomFuncA1; + T2_CustomFuncB CustomFuncB1; } T2_InitializeOptions;</code></pre> -<p>and the following GlueGen <em>no-magic</em> configuration</p> +<p>and the following GlueGen configuration</p> <pre><code>Opaque long void* EmitStruct T2_UserData @@ -1745,6 +1805,17 @@ StructPackage T2_InitializeOptions com.jogamp.gluegen.test.junit.generation</cod /** Interface to C language function: <br> <code>int32_t CustomFuncB1(T2_UserData * pUserData)</code><br> */ public final int CustomFuncB1(T2_UserData pUserData) { .. } </code></pre> +<h3 id="java-callback-from-native-c-api-support">Java Callback from +Native C-API Support</h3> +<p>GlueGen supports registering Java callback methods to native C-API +functions in the form:</p> +<pre><code>typedef int32_t ( * T_CallbackFunc)(size_t id, size_t msg_len, const char* msg, void* userParam); + +void AddMessageCallback(T_CallbackFunc func, void* userParam); +void RemoveMessageCallback(T_CallbackFunc func, void* userParam); +void InjectMessageCallback(size_t id, size_t msg_len, const char* msg);</code></pre> +<p><em>TODO: Work in progress</em></p> +<h4 id="example-1">Example</h4> <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 87124e7..2a0de78 100644 --- a/doc/GlueGen_Mapping.md +++ b/doc/GlueGen_Mapping.md @@ -80,6 +80,15 @@ Gluegen has build-in types (terminal symbols) for: * Anonymous void-pointer _void\*_ are mapped to NIO _Buffer_. * Pointers to pointer-size types like _intptr\_t\*_, _uintptr\_t\*_, _ptrdiff\_t\*_ and _size\_t\*_ are mapped to _PointerBuffer_, to reflect the architecture depending storage size. +### Pointer Mapping +*Pointer* values itself are represented as `long` values on the Java side +while using the native pointer-size, e.g. 32-bit or 64-bit, on the native end. + +They may simply be accessible via `long` or `long[]` primitives in Java, +or are exposed via `com.jogamp.common.nio.PointerBuffer`. + +See [Struct Pointer-Pointer Support](#struct-pointer-pointer-support) below. + ### String Mapping #### Function return String values @@ -199,14 +208,16 @@ A *Struct* is a C compound type declaration, which can be mapped to a Java class A *Struct* may utilize the following data types for its fields * *Primitive*, i.e. *char*, *int32_t*, ... * See [*Primitive Mapping*](#primitive-mapping) above. + * See [*Pointer Mapping*](#pointer-mapping) for *pointer-to-pointer* values above and [Struct Pointer-Pointer Support](#struct-pointer-pointer-support) below. * See [*String Mapping*](#string-mapping) above. -* *Struct*, i.e. another compound variable -* *Function Pointer*, a *typedef*'ed and set callable function pointer +* *Struct*, i.e. an aggregated or referenced compound variable +* *Function Pointer*, a *typedef*'ed and set callable function pointer, see [Struct Function-Pointer Support](#struct-function-pointer-support) below. +* *Java Callback from Native Code*, see [section below](#java-callback-from-native-c-api-support) A field may be a direct aggregation, i.e. instance, within the struct including an array or a reference to a single element or array via a pointer. -Both, *primitive* and *struct* field type mappings only produce pure Java code, utilizing the *GlueGen Runtime*. +Both, *primitive*, *struct* and *pointer* field type mappings only produce pure Java code, utilizing the *GlueGen Runtime*. Hence no additional native code must be compiled nor a resulting additional library loaded to use the mapping. Only when mapping *function-pointer* within *structs*, additional native glue-code is produced to @@ -537,7 +548,42 @@ A similar mapping is produced for `struct` types, i.e. *compounds*. Returns: * this instance of chaining -### Struct Function Pointer Support +### Struct Pointer-Pointer Support +See primitive [*Pointer Mapping*](#pointer-mapping) above. + +*Pointer* are exposed in the following examples +``` +typedef struct { + int32_t* int32PtrArray[10]; + int32_t** int32PtrPtr; + + ... +} T2_PointerStorage; +``` + +or via and undefined forward-declared struct +``` +typedef struct T2_UndefStruct* T2_UndefStructPtr; + +typedef struct { + ... + + T2_UndefStructPtr undefStructPtr; + T2_UndefStructPtr undefStructPtrArray[10]; + T2_UndefStructPtr* undefStructPtrPtr; + const T2_UndefStructPtr* constUndefStructPtrPtr; +} T2_PointerStorage; +``` + +and the following GlueGen configuration +``` +Opaque long T2_UndefStruct* +Ignore T2_UndefStruct +``` + +*TODO: Enhance documentation* + +### Struct Function-Pointer Support GlueGen supports function pointers as struct fields, generating function calls as methods as well function-pointer opaque getter and setter as `long` types. The latter only in case if mutable, i.e. non-const. @@ -554,12 +600,24 @@ typedef int32_t ( * T2_CustomFuncA)(void* aptr); typedef int32_t ( * T2_CustomFuncB)(T2_UserData* pUserData); typedef struct { - const T2_CustomFuncA CustomFuncA1; - T2_CustomFuncB CustomFuncB1; + ... + + T2_CustomFuncA customFuncAVariantsArray[10]; + T2_CustomFuncA* customFuncAVariantsArrayPtr; + + T2_CustomFuncB customFuncBVariantsArray[10]; + T2_CustomFuncB* customFuncBVariantsArrayPtr; +} T2_PointerStorage; + +typedef struct { + ... + + const T2_CustomFuncA CustomFuncA1; + T2_CustomFuncB CustomFuncB1; } T2_InitializeOptions; ``` -and the following GlueGen *no-magic* configuration +and the following GlueGen configuration ``` Opaque long void* @@ -606,6 +664,20 @@ and similar to `T2_CustomFuncB customFuncB1` public final int CustomFuncB1(T2_UserData pUserData) { .. } ``` +### Java Callback from Native C-API Support +GlueGen supports registering Java callback methods to native C-API functions in the form: +``` +typedef int32_t ( * T_CallbackFunc)(size_t id, size_t msg_len, const char* msg, void* userParam); + +void AddMessageCallback(T_CallbackFunc func, void* userParam); +void RemoveMessageCallback(T_CallbackFunc func, void* userParam); +void InjectMessageCallback(size_t id, size_t msg_len, const char* msg); +``` + +*TODO: Work in progress* + +#### Example + ## Platform Header Files GlueGen provides convenient platform headers, diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh index cf1aa6d..40cd4c5 100755 --- a/make/scripts/runtest.sh +++ b/make/scripts/runtest.sh @@ -151,8 +151,9 @@ function onetest() { #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.Test1p2DynamicLibraryBundle 2>&1 | tee -a $LOG onetest com.jogamp.gluegen.test.junit.generation.Test2FuncPtr 2>&1 | tee -a $LOG +onetest com.jogamp.gluegen.test.junit.generation.Test3PtrStorage 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 110bf50..4fcec8f 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -1052,7 +1052,7 @@ public class JavaEmitter implements GlueEmitter { } javaUnit.emitln(" /** Returns new instance dereferencing ByteBuffer at given native address `addr` with size {@link #size()}. */"); javaUnit.emitln(" public static " + containingJTypeName + " derefPointer(final long addr) {"); - javaUnit.emitln(" return create( ElementBuffer.derefPointer(size(), 1, addr).getByteBuffer() );"); + javaUnit.emitln(" return create( ElementBuffer.derefPointer(size(), addr, 1).getByteBuffer() );"); javaUnit.emitln(" }"); javaUnit.emitln(); if( !cfg.manuallyImplement(JavaConfiguration.canonicalStructFieldSymbol(containingJTypeName, containingJTypeName)) ) { @@ -1091,12 +1091,13 @@ public class JavaEmitter implements GlueEmitter { final boolean immutableField = immutableStruct || cfg.immutableAccess(fqStructFieldName1); if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: %s / %s (opaque %b), %s (opaque %b), immutable[struct %b, field %b]%n", (i+1), - (i+1), field, fqStructFieldName1, isOpaqueField, fieldType.getDebugString(), isOpaqueFieldType, + System.err.printf("SE.ac.%02d: field %s / %s / rename %s -> %s / opaque %b, fieldType %s (opaque %b), immutable[struct %b, field %b]%n", (i+1), + field, fqStructFieldName1, renamed, fieldName, isOpaqueField, fieldType.getDebugString(), isOpaqueFieldType, immutableStruct, immutableField); + System.err.printf("SE.ac.%02d: opaqueFieldType %s%n", (i+1), opaqueFieldType); } if ( fieldType.isFunctionPointer() && !isOpaqueField ) { - final FunctionSymbol func = new FunctionSymbol(field.getName(), fieldType.asPointer().getTargetType().asFunction()); + final FunctionSymbol func = new FunctionSymbol(field.getName(), fieldType.getTargetFunction()); func.rename(renamed); // null is OK final String javaTypeName = "long"; final String capFieldName = capitalizeString(fieldName); @@ -1251,11 +1252,16 @@ public class JavaEmitter implements GlueEmitter { relationship = "being"; } else if( fieldType.isPointer() ) { isArray = true; - referencedType = fieldType.getBaseType(); + referencedType = fieldType.getTargetType(); relationship = "referencing"; } else if( fieldType.isArray() ) { isArray = true; - referencedType = null; + final Type t = fieldType.getArrayBaseOrPointerTargetType(); + if( t != fieldType && t.isPointer() ) { + referencedType = t; + } else { + referencedType = null; + } relationship = "being"; } else { isArray = false; @@ -1614,25 +1620,21 @@ public class JavaEmitter implements GlueEmitter { final boolean immutableAccess, 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 \"" + - fqStructFieldName + "\", "+fieldType.getDebugString(), fieldType.getASTLocusTag(), e); - } + final TypeInfo opaqueTypeInfo = cfg.typeInfo(fieldType); + final boolean isOpaque = null != opaqueTypeInfo; + final Type baseElemType = fieldType.getArrayBaseOrPointerTargetType(); if( GlueGen.debug() ) { - 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()); + 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: opaqueInfo %b, %s%n", (i+1), isOpaque, opaqueTypeInfo); + System.err.printf("SE.ac.%02d: baseElemType %s, %s%n", (i+1), baseElemType.toString(), baseElemType.getSignature(null).toString()); } // // Collect all required information including considering Opaque types // final String containingJTypeName = containingJType.getName(); - final boolean isOpaque = isOpaque(fieldType); final boolean isStringOnly = cfg.returnsStringOnly(fqStructFieldName); // exclude alternative ByteBuffer representation to String final boolean isString = isStringOnly || cfg.returnsString(fqStructFieldName); if( isString ) { @@ -1648,11 +1650,12 @@ public class JavaEmitter implements GlueEmitter { final boolean staticElemCount; final JavaType baseJElemType; final String baseJElemTypeName; - final boolean primCElemFixedSize; // Is Primitive element size fixed? If not, use md.*_Size[] - final String baseCElemSizeDenominator; + final boolean primElemFixedSize; // Is Primitive element size fixed? If not, use md.*_Size[] + final boolean baseIsPointer; // Is Primitive element a pointer? + final String baseElemSizeDenominator; final boolean useGetCStringLength; final boolean maxOneElement; // zero or one element - if( isOpaque || javaType.isPrimitive() ) { + if( isOpaque && opaqueTypeInfo.pointerDepth() <= 1 || ( fieldType.isPrimitive() && !baseElemType.isFunctionPointer() ) ) { // Overridden by JavaConfiguration.typeInfo(..), i.e. Opaque! // Emulating array w/ 1 element isPrimitive = true; @@ -1663,37 +1666,27 @@ public class JavaEmitter implements GlueEmitter { ownership = Ownership.Parent; staticElemCount = true; baseJElemType = null; - baseJElemTypeName = compatiblePrimitiveJavaTypeName(fieldType, javaType, machDescJava); - primCElemFixedSize = false; - baseCElemSizeDenominator = fieldType.isPointer() ? "pointer" : baseJElemTypeName ; + baseJElemTypeName = compatiblePrimitiveJavaTypeName(fieldType, machDescJava); + primElemFixedSize = false; + baseIsPointer = fieldType.isPointer(); + baseElemSizeDenominator = baseIsPointer ? "pointer" : baseJElemTypeName ; useGetCStringLength = false; maxOneElement = true; } else { - final ArrayType arrayType = fieldType.asArray(); - final Type baseCElemType; - if( null != arrayType ) { + if( fieldType.arrayDimension() > 0 ) { final int[][] arrayLengthRes = new int[1][]; final boolean[] _useFixedArrayLen = { false }; - elemCountExpr = getArrayArrayLengthExpr(arrayType, fqStructFieldName, _useFixedArrayLen, arrayLengthRes); + elemCountExpr = getArrayArrayLengthExpr(fieldType.asArray(), fqStructFieldName, _useFixedArrayLen, arrayLengthRes); // final int arrayLength = arrayLengthRes[0][0]; constElemCount = _useFixedArrayLen[0]; ownership = Ownership.Parent; // a fixed linear array staticElemCount = constElemCount; - baseCElemType = arrayType.getBaseType(); + // baseCElemType = pointerType.getBaseType(); isPointer = false; useGetCStringLength = false; } else { - final PointerType pointerType = fieldType.asPointer(); final String _elemCountExpr = cfg.returnedArrayLength(fqStructFieldName); - baseCElemType = pointerType.getBaseType(); isPointer = true; - if( 1 != pointerType.pointerDepth() ) { - final String msg = "SKIP ptr-ptr (depth "+pointerType.pointerDepth()+"): "+fqStructFieldName +": "+fieldType; - unit.emitln(" // "+msg); - unit.emitln(); - LOG.log(WARNING, structCType.getASTLocusTag(), msg); - return; - } if( null == _elemCountExpr && isString ) { useGetCStringLength = true; unit.addTailCode(optStringMaxStrnlenCode); @@ -1746,7 +1739,8 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" // "+msg); unit.emitln(); LOG.log(WARNING, structCType.getASTLocusTag(), msg); - return; + throw new InternalError(msg); + // return; // FIXME: Remove block unreachable } boolean _maxOneElement = cfg.maxOneElement(fqStructFieldName); if( !_maxOneElement ) { @@ -1756,41 +1750,45 @@ public class JavaEmitter implements GlueEmitter { } maxOneElement = _maxOneElement; if( GlueGen.debug() ) { - System.err.printf("SE.ac.%02d: baseCType ownership %s, %s%n", (i+1), ownership, baseCElemType.getSignature(null).toString()); + System.err.printf("SE.ac.%02d: ownership %s%n", (i+1), ownership); } - if( !baseCElemType.hasSize() ) { // like 'void*' -> 'void' - final String msg = "SKIP unsized field in struct: "+fqStructFieldName+": fieldType "+fieldType.getSignature(null).toString()+", baseType "+baseCElemType.getSignature(null).toString(); + if( !baseElemType.hasSize() ) { // like 'void*' -> 'void' + final String msg = "SKIP unsized field in struct: "+fqStructFieldName+": fieldType "+fieldType.getSignature(null).toString()+", baseType "+baseElemType.getSignature(null).toString(); unit.emitln(" // "+msg); unit.emitln(); LOG.log(WARNING, structCType.getASTLocusTag(), msg); return; } - isPrimitive = baseCElemType.isPrimitive(); - isConstValue = baseCElemType.isConst(); - try { - baseJElemType = typeToJavaType(baseCElemType, machDescJava); - } catch (final Exception e ) { - throw new GlueGenException("Error occurred while creating array/pointer accessor for field \"" + - fqStructFieldName + "\", baseType "+baseCElemType.getDebugString()+", topType "+fieldType.getDebugString(), - fieldType.getASTLocusTag(), e); + baseIsPointer = baseElemType.isPointer(); + isConstValue = baseElemType.isConst(); + if( baseIsPointer ) { + baseJElemType = javaType(Long.TYPE); // forced mapping pointer-pointer -> long + } else { + try { + baseJElemType = typeToJavaType(baseElemType, machDescJava); + } catch (final Exception e ) { + throw new GlueGenException("Error occurred while creating array/pointer accessor for field \"" + + fqStructFieldName + "\", baseType "+baseElemType.getDebugString()+", topType "+fieldType.getDebugString(), + fieldType.getASTLocusTag(), e); + } } baseJElemTypeName = baseJElemType.getName(); - primCElemFixedSize = isPrimitive ? baseCElemType.getSize().hasFixedNativeSize() : false; - baseCElemSizeDenominator = baseCElemType.isPointer() ? "pointer" : baseJElemTypeName ; + isPrimitive = baseJElemType.isPrimitive() || baseElemType.isPrimitive() || baseElemType.isFunctionPointer(); + primElemFixedSize = isPrimitive ? baseElemType.getSize().hasFixedNativeSize() : false; + baseElemSizeDenominator = baseIsPointer ? "pointer" : baseJElemTypeName ; } if( GlueGen.debug() ) { System.err.printf("SE.ac.%02d: baseJElemType %s%n", (i+1), (null != baseJElemType ? baseJElemType.getDebugString() : null)); } // Collect fixed primitive-type mapping metrics - final Class<? extends Buffer> primJElemTypeBufferClazz; final String primJElemTypeBufferName; final int primElemSize; final String primElemSizeExpr; final boolean isByteBuffer; if( isPrimitive ) { - primJElemTypeBufferClazz = Buffers.typeNameToBufferClass(baseJElemTypeName); + final Class<? extends Buffer> primJElemTypeBufferClazz = Buffers.typeNameToBufferClass(baseJElemTypeName); if( null == primJElemTypeBufferClazz ) { final String msg = "Failed to map '"+baseJElemTypeName+"' to Buffer class, field "+field+", j-type "+baseJElemType; unit.emitln(" // ERROR: "+msg); @@ -1801,13 +1799,12 @@ public class JavaEmitter implements GlueEmitter { primJElemTypeBufferName = primJElemTypeBufferClazz.getSimpleName(); primElemSize = Buffers.sizeOfBufferElem(primJElemTypeBufferClazz); isByteBuffer = null != primJElemTypeBufferClazz ? ByteBuffer.class.isAssignableFrom(primJElemTypeBufferClazz) : false; - if( primCElemFixedSize ) { + if( primElemFixedSize ) { primElemSizeExpr = String.valueOf(primElemSize); } else { - primElemSizeExpr = "md."+baseCElemSizeDenominator+"SizeInBytes()"; + primElemSizeExpr = "md."+baseElemSizeDenominator+"SizeInBytes()"; } } else { - primJElemTypeBufferClazz = null; primJElemTypeBufferName = null; primElemSize = 0; isByteBuffer = false; @@ -1839,12 +1836,12 @@ public class JavaEmitter implements GlueEmitter { if( GlueGen.debug() ) { System.err.printf("SE.ac.%02d: baseJElemTypeName %s%n", (i+1), baseJElemTypeName); System.err.printf("SE.ac.%02d: elemCountExpr: %s (const %b, ownership %s), ownArrayLenCpde %b, maxOneElement %b, "+ - "Primitive[buffer %s, fixedSize %b, elemSize %d, sizeDenom %s, sizeExpr %s, isByteBuffer %b], "+ - "isString[%b, only %b, strnlen %b], isPointer %b, isPrimitive %b, isOpaque %b, constVal %b, immutableAccess %b%n", + "Primitive[is %b, aptr %b, buffer %s, fixedSize %b, elemSize %d, sizeDenom %s, sizeExpr %s, isByteBuffer %b], "+ + "isString[%b, only %b, strnlen %b], isPointer %b, isOpaque %b, constVal %b, immutableAccess %b%n", (i+1), elemCountExpr, constElemCount, ownership, ownElemCountHandling, maxOneElement, - primJElemTypeBufferName, primCElemFixedSize, primElemSize, baseCElemSizeDenominator, primElemSizeExpr, isByteBuffer, + isPrimitive, baseIsPointer, primJElemTypeBufferName, primElemFixedSize, primElemSize, baseElemSizeDenominator, primElemSizeExpr, isByteBuffer, isString, isStringOnly, useGetCStringLength, - isPointer, isPrimitive, isOpaque, isConstValue, immutableAccess); + isPointer, isOpaque, isConstValue, immutableAccess); } // @@ -1889,7 +1886,11 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" return this;"); unit.emitln(" }"); unit.emitln(" @SuppressWarnings(\"unused\")"); - unit.emitln(" private ElementBuffer _eb"+capitalFieldName+"; // cache new memory buffer ensuring same lifecycle"); + if( baseIsPointer ) { + unit.emitln(" private PointerBuffer _eb"+capitalFieldName+"; // cache new memory buffer ensuring same lifecycle"); + } else { + unit.emitln(" private ElementBuffer _eb"+capitalFieldName+"; // cache new memory buffer ensuring same lifecycle"); + } unit.emitln(); } } @@ -1917,12 +1918,17 @@ public class JavaEmitter implements GlueEmitter { 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);"); - unit.emit (" eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( baseIsPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.allocateDirect(1);"); + unit.emitln(" eb.put(0, src);"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", 1);"); + unit.emit (" eb.getByteBuffer()"); + if( !isByteBuffer ) { + unit.emit(".as"+primJElemTypeBufferName+"()"); + } + unit.emitln(".put(0, src);"); } - unit.emitln(".put(0, src);"); unit.emitln(" eb.storeDirectAddress(getBuffer(), "+fieldName+"_offset[mdIdx]);"); unit.emitln(" _eb"+capitalFieldName+" = eb;"); emitSetElemCount(unit, setElemCountLengthFunc, "1", !useGetCStringLength, capitalFieldName, structCType, " "); @@ -1932,12 +1938,17 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" {"); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( 1 == elemCount ) {"); - unit.emitln(" ElementBuffer.derefPointer("+primElemSizeExpr+", 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); - unit.emit (" .getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( baseIsPointer ) { + unit.emitln(" PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + unit.emitln(" .put(0, src);"); + } else { + unit.emitln(" ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + unit.emit (" .getByteBuffer()"); + if( !isByteBuffer ) { + unit.emit(".as"+primJElemTypeBufferName+"()"); + } + unit.emitln(".put(0, src);"); } - unit.emitln(".put(0, src);"); unit.emitln(" } else {"); if( constElemCount || Ownership.Native == ownership ) { unit.emitln(" throw new RuntimeException(\"Primitive '"+fieldName+"' of "+ownership+" ownership and maxOneElement has " @@ -1946,12 +1957,17 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" return this;"); unit.emitln(" }"); } else { - unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", 1);"); - unit.emit (" eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( baseIsPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.allocateDirect(1);"); + unit.emitln(" eb.put(0, src);"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", 1);"); + unit.emit (" eb.getByteBuffer()"); + if( !isByteBuffer ) { + unit.emit(".as"+primJElemTypeBufferName+"()"); + } + unit.emitln(".put(0, src);"); } - unit.emitln(".put(0, src);"); unit.emitln(" eb.storeDirectAddress(getBuffer(), "+fieldName+"_offset[mdIdx]);"); unit.emitln(" _eb"+capitalFieldName+" = eb;"); emitSetElemCount(unit, setElemCountLengthFunc, "1", !useGetCStringLength, capitalFieldName, structCType, " "); @@ -1964,12 +1980,16 @@ public class JavaEmitter implements GlueEmitter { generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, null, baseJElemTypeName, null, constElemCount, maxOneElement, elemCountExpr, null, null); unit.emitln(" {"); - unit.emitln(" ElementBuffer.wrap("+primElemSizeExpr+", 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); - unit.emit (" .getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( baseIsPointer ) { + unit.emitln(" PointerBuffer.wrap(getBuffer(), "+fieldName+"_offset[mdIdx], 1).put(0, src);"); + } else { + unit.emitln(" ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + unit.emit (" .getByteBuffer()"); + if( !isByteBuffer ) { + unit.emit(".as"+primJElemTypeBufferName+"()"); + } + unit.emitln(".put(0, src);"); } - unit.emitln(".put(0, src);"); unit.emitln(" return this;"); unit.emitln(" }"); } // else SKIP setter for constValue Array @@ -1988,7 +2008,7 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( srcBytes.length + 1 != elemCount ) { throw new IllegalArgumentException(\"strlen+1 \"+(srcBytes.length+1)+\" != " +(constElemCount?"const":"")+" elemCount \"+elemCount+\" of "+ownership+" ownership\"); };"); - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } else { unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", srcBytes.length + 1);"); } @@ -2014,14 +2034,13 @@ public class JavaEmitter implements GlueEmitter { throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString()); } unit.emitln(" {"); - unit.emitln(SetReplaceArrayArgsCheck); - unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", length);"); - unit.emit (" eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + // JAU01 unit.emitln(SetReplaceArrayArgsCheck); + if( baseIsPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.allocateDirect(length);"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", length);"); } - unit.emitln(".put(src, srcPos, length).rewind();"); - unit.emitln(" eb.storeDirectAddress(getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" eb.put(src, srcPos, 0, length).storeDirectAddress(getBuffer(), "+fieldName+"_offset[mdIdx]);"); unit.emitln(" _eb"+capitalFieldName+" = eb;"); emitSetElemCount(unit, setElemCountLengthFunc, "length", !useGetCStringLength, capitalFieldName, structCType, " "); unit.emitln(" return this;"); @@ -2031,19 +2050,23 @@ public class JavaEmitter implements GlueEmitter { generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, null, baseJElemTypeName+"[]", SetSubArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetSubArrayApiDocDetail, SetSubArrayApiDocArgs); unit.emitln(" {"); - unit.emitln(SetSubArrayArgsCheck); + // JAU01 unit.emitln(SetSubArrayArgsCheck); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); - unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); - if( isPointer ) { - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + // JAU01 unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); + if( baseIsPointer ) { + if( isPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + } else { + unit.emitln(" final PointerBuffer eb = PointerBuffer.wrap(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + } } else { - unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); - } - unit.emit (" ( ("+primJElemTypeBufferName+") eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( isPointer ) { + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + } } - unit.emitln(".position(destPos) ).put(src, srcPos, length).rewind();"); + unit.emitln(" eb.put(src, srcPos, destPos, length);"); unit.emitln(" return this;"); unit.emitln(" }"); } else /* if( !constElemCount && isPointer ) */ { @@ -2053,34 +2076,33 @@ public class JavaEmitter implements GlueEmitter { throw new InternalError("Native ownership but adding potential memory-replacement for '"+fqStructFieldName+"': "+fieldType.getSignature(null).toString()); } unit.emitln(" {"); - unit.emitln(SetArrayArgsCheck); + // JAU01 unit.emitln(SetArrayArgsCheck); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( subset || destPos + length == elemCount ) {"); - unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"subset \"+subset+\", destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); - unit.emit (" ( ("+primJElemTypeBufferName+") eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + // JAU01 unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"subset \"+subset+\", destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); + if( baseIsPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } - unit.emitln(".position(destPos) ).put(src, srcPos, length).rewind();"); + unit.emitln(" eb.put(src, srcPos, destPos, length);"); unit.emitln(" } else {"); unit.emitln(" final int newElemCount = destPos + length;"); - unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", newElemCount);"); - unit.emit (" final "+primJElemTypeBufferName+" ebBB = eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); - } - unit.emitln(";"); - unit.emitln(" if( 0 < destPos ) {"); - unit.emitln(" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); - unit.emit (" final "+primJElemTypeBufferName+" pre_ebBB = ("+primJElemTypeBufferName+") pre_eb.getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( baseIsPointer ) { + unit.emitln(" final PointerBuffer eb = PointerBuffer.allocateDirect(newElemCount);"); + unit.emitln(" if( 0 < destPos ) {"); + unit.emitln(" final PointerBuffer pre_eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + unit.emitln(" pre_eb.position(0).limit(destPos);"); + unit.emitln(" eb.put(pre_eb).rewind();"); + unit.emitln(" }"); + } else { + unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+", newElemCount);"); + unit.emitln(" if( 0 < destPos ) {"); + unit.emitln(" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); + unit.emitln(" eb.put(pre_eb.getByteBuffer(), 0, 0, destPos);"); + unit.emitln(" }"); } - unit.emitln(".position(0).limit(destPos);"); - unit.emitln(" ebBB.put(pre_ebBB);"); - unit.emitln(" }"); - unit.emitln(" ebBB.put(src, srcPos, length).rewind();"); + unit.emitln(" eb.put(src, srcPos, destPos, length);"); unit.emitln(" eb.storeDirectAddress(getBuffer(), "+fieldName+"_offset[mdIdx]);"); unit.emitln(" _eb"+capitalFieldName+" = eb;"); emitSetElemCount(unit, setElemCountLengthFunc, "newElemCount", !useGetCStringLength, capitalFieldName, structCType, " "); @@ -2114,7 +2136,7 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" {"); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( 1 == elemCount ) {"); - unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); unit.emitln(" .put(0, src.getBuffer());"); unit.emitln(" } else {"); if( constElemCount || Ownership.Native == ownership ) { @@ -2138,7 +2160,7 @@ public class JavaEmitter implements GlueEmitter { generateSetterSignature(unit, accessMod, false, false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, null, baseJElemTypeName, null, constElemCount, maxOneElement, elemCountExpr, null, null); unit.emitln(" {"); - unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); unit.emitln(" .put(0, src.getBuffer());"); unit.emitln(" return this;"); unit.emitln(" }"); @@ -2174,9 +2196,9 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); if( isPointer ) { - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } else { - unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } unit.emitln(" for(int i=0; i<length; ++i) {"); unit.emitln(" eb.put(destPos+i, src[srcPos+i].getBuffer());"); @@ -2194,7 +2216,7 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( subset || destPos + length == elemCount ) {"); unit.emitln(" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"subset \"+subset+\", destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); unit.emitln(" for(int i=0; i<length; ++i) {"); unit.emitln(" eb.put(destPos+i, src[srcPos+i].getBuffer());"); unit.emitln(" }"); @@ -2203,7 +2225,7 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+".size(), newElemCount);"); unit.emitln(" if( 0 < destPos ) {"); - unit.emitln(" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); unit.emitln(" eb.put(pre_eb.getByteBuffer(), 0, 0, destPos);"); unit.emitln(" }"); unit.emitln(" for(int i=0; i<length; ++i) {"); @@ -2224,9 +2246,9 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( destPos + 1 > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + 1 > elemCount \"+elemCount); };"); if( isPointer ) { - unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); } else { - unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); } unit.emitln(" .put(destPos, src.getBuffer());"); unit.emitln(" return this;"); @@ -2243,14 +2265,22 @@ public class JavaEmitter implements GlueEmitter { generateGetterSignature(unit, false, false, fieldName, fieldType, ownership, baseJElemTypeName, capitalFieldName, null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail); unit.emitln(" {"); - if( isPointer ) { - unit.emitln(" return ElementBuffer.derefPointer("+primElemSizeExpr+", 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); + if( baseIsPointer ) { + if( isPointer ) { + unit.emit (" return PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + } else { + unit.emit (" return PointerBuffer.wrap(getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + } } else { - unit.emitln(" return ElementBuffer.wrap("+primElemSizeExpr+", 1, getBuffer(), "+fieldName+"_offset[mdIdx])"); - } - unit.emit (" .getByteBuffer()"); - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( isPointer ) { + unit.emitln(" return ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + } else { + unit.emitln(" return ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], 1)"); + } + unit.emit (" .getByteBuffer()"); + if( !isByteBuffer ) { + unit.emit(".as"+primJElemTypeBufferName+"()"); + } } unit.emitln(".get(0);"); unit.emitln(" }"); @@ -2263,9 +2293,9 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" {"); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); if( isPointer ) { - unit.emitln(" final ByteBuffer bb = ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer();"); + unit.emitln(" final ByteBuffer bb = ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount).getByteBuffer();"); } else { - unit.emitln(" final ByteBuffer bb = ElementBuffer.wrap("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer();"); + unit.emitln(" final ByteBuffer bb = ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount).getByteBuffer();"); } unit.emitln(" final byte[] ba = new byte[elemCount];"); unit.emitln(" int i = -1;"); @@ -2281,14 +2311,14 @@ public class JavaEmitter implements GlueEmitter { if( doneString && isStringOnly ) { generateArrayFieldNote(unit, " /** SKIP getter for String alternative (ByteBuffer)", " */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr, false, false); unit.emitln(); - } else { + } else if( !baseIsPointer ) { generateGetterSignature(unit, false, false, fieldName, fieldType, ownership, primJElemTypeBufferName, capitalFieldName, null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail); unit.emitln(" {"); if( isPointer ) { - unit.emitln(" return ElementBuffer.derefPointer("+primElemSizeExpr+", "+getElemCountFuncExpr+", getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" return ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], "+getElemCountFuncExpr+")"); } else { - unit.emitln(" return ElementBuffer.wrap("+primElemSizeExpr+", "+getElemCountFuncExpr+", getBuffer(), "+fieldName+"_offset[mdIdx])"); + unit.emitln(" return ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], "+getElemCountFuncExpr+")"); } unit.emit (" .getByteBuffer()"); if( !isByteBuffer ) { @@ -2302,20 +2332,21 @@ public class JavaEmitter implements GlueEmitter { generateGetterSignature(unit, false, false, fieldName, fieldType, ownership, baseJElemTypeName+"[]", capitalFieldName, "final int srcPos, "+baseJElemTypeName+" dest[], "+GetArrayArgs, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail); unit.emitln(" {"); - unit.emitln(GetArrayArgsCheck); unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); - unit.emitln(" if( srcPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"srcPos \"+srcPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); - unit.emit (" ( ("+primJElemTypeBufferName+")( "); - if( isPointer ) { - unit.emit("ElementBuffer.derefPointer("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer()"); + if( baseIsPointer ) { + if( isPointer ) { + unit.emit (" PointerBuffer.derefPointer(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); + } else { + unit.emit (" PointerBuffer.wrap(getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); + } } else { - unit.emit("ElementBuffer.wrap("+primElemSizeExpr+", elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer()"); - } - if( !isByteBuffer ) { - unit.emit(".as"+primJElemTypeBufferName+"()"); + if( isPointer ) { + unit.emit(" ElementBuffer.derefPointer("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); + } else { + unit.emit(" ElementBuffer.wrap("+primElemSizeExpr+", getBuffer(), "+fieldName+"_offset[mdIdx], elemCount)"); + } } - unit.emitln(".position(srcPos) ) )"); - unit.emitln(" .get(dest, destPos, length).rewind();"); + unit.emitln(".get(srcPos, dest, destPos, length);"); unit.emitln(" return dest;"); unit.emitln(" }"); unit.emitln(); @@ -2329,9 +2360,9 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" {"); unit.emitln(" return "+baseJElemTypeName+".create("); if( isPointer ) { - unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), 1, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer() );"); + unit.emitln(" ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], 1).getByteBuffer() );"); } else { - unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), 1, getBuffer(), "+fieldName+"_offset[mdIdx]).getByteBuffer() );"); + unit.emitln(" ElementBuffer.wrap("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], 1).getByteBuffer() );"); } unit.emitln(" }"); unit.emitln(); @@ -2343,9 +2374,9 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" final int elemCount = "+getElemCountFuncExpr+";"); unit.emitln(" if( srcPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"srcPos \"+srcPos+\" + length \"+length+\" > elemCount \"+elemCount); };"); if( isPointer ) { - unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } else { - unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+".size(), elemCount, getBuffer(), "+fieldName+"_offset[mdIdx]);"); + unit.emitln(" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+".size(), getBuffer(), "+fieldName+"_offset[mdIdx], elemCount);"); } unit.emitln(" for(int i=0; i<length; ++i) {"); unit.emitln(" dest[destPos+i] = "+baseJElemTypeName+".create( eb.slice(srcPos+i, 1) );"); @@ -2438,6 +2469,8 @@ public class JavaEmitter implements GlueEmitter { if (cType.pointerDepth() == 1 || cType.arrayDimension() == 1) { if (targetType.isVoid()) { return JavaType.createForCVoidPointer(); + } else if( targetType.isFunctionPointer() ) { + return javaType(Long.TYPE); } else if (targetType.isInt()) { final SizeThunk targetSizeThunk = targetType.getSize(); if( null != targetSizeThunk && SizeThunk.POINTER == targetSizeThunk ) { @@ -2586,14 +2619,6 @@ public class JavaEmitter implements GlueEmitter { } } - private static boolean isIntegerType(final Class<?> c) { - return ((c == Byte.TYPE) || - (c == Short.TYPE) || - (c == Character.TYPE) || - (c == Integer.TYPE) || - (c == Long.TYPE)); - } - private StructLayout getLayout() { if (layout == null) { layout = StructLayout.create(0); @@ -2627,21 +2652,18 @@ public class JavaEmitter implements GlueEmitter { } private String compatiblePrimitiveJavaTypeName(final Type fieldType, - final JavaType javaType, final MachineDataInfo curMachDesc) { - final Class<?> c = javaType.getJavaClass(); - if (!isIntegerType(c)) { - // FIXME - throw new GlueGenException("Can't yet handle opaque definitions of structs' fields to non-integer types (byte, short, int, long, etc.): type: "+fieldType+", javaType "+javaType+", javaClass "+c, - fieldType.getASTLocusTag()); + if ( !fieldType.isInt() && !fieldType.isPointer() && !fieldType.isArray() ) { + throw new GlueGenException("Can't yet handle opaque definitions of structs' fields to non-integer types (byte, short, int, long, etc.): type: "+ + fieldType, fieldType.getASTLocusTag()); } switch ((int) fieldType.getSize(curMachDesc)) { case 1: return "byte"; case 2: return "short"; case 4: return "int"; case 8: return "long"; - default: throw new GlueGenException("Can't handle opaque definitions if the starting type isn't compatible with integral types", - fieldType.getASTLocusTag()); + default: throw new GlueGenException("Can't handle opaque definitions if the starting type isn't compatible with integral types, type "+ + fieldType.getDebugString(), fieldType.getASTLocusTag()); } } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test2FuncPtr.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test2FuncPtr.java index 66c7178..3503fa3 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test2FuncPtr.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test2FuncPtr.java @@ -114,6 +114,14 @@ public class Test2FuncPtr extends BaseClass { Assert.assertEquals(404, ud2.getBalance()); Assert.assertEquals("Jane Doe", ud2.getName()); } + // Check func-ptr are original + { + final long[] funcBOrigs = options.getCustomFuncBVariants(0, new long[2], 0, 2); + final long funcB1 = options.getCustomFuncB1(); + final long funcB2 = options.getCustomFuncB2(); + Assert.assertEquals(funcBOrigs[0], funcB1); + Assert.assertEquals(funcBOrigs[1], funcB2); + } Assert.assertEquals(101, options.CustomFuncB1(ud1)); Assert.assertEquals(404, options.CustomFuncB1(ud2)); Assert.assertEquals(-101, options.CustomFuncB2(ud1)); @@ -125,6 +133,14 @@ public class Test2FuncPtr extends BaseClass { options.setCustomFuncB1(funcB2); options.setCustomFuncB2(funcB1); } + // Check func-ptr are switched + { + final long[] funcBOrigs = options.getCustomFuncBVariants(0, new long[2], 0, 2); + final long funcB1 = options.getCustomFuncB1(); + final long funcB2 = options.getCustomFuncB2(); + Assert.assertEquals(funcBOrigs[1], funcB1); + Assert.assertEquals(funcBOrigs[0], funcB2); + } Assert.assertEquals(-101, options.CustomFuncB1(ud1)); Assert.assertEquals(-404, options.CustomFuncB1(ud2)); Assert.assertEquals(101, options.CustomFuncB2(ud1)); diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test3PtrStorage.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test3PtrStorage.java new file mode 100644 index 0000000..2bf82a8 --- /dev/null +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test3PtrStorage.java @@ -0,0 +1,139 @@ +/** + * 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 java.nio.IntBuffer; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.nio.ElementBuffer; +import com.jogamp.common.os.NativeLibrary; +import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest2Impl; + +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_PointerStorage} instance and pointer pointer.. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class Test3PtrStorage 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, Test2FuncPtr.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 {@link Bindingtest2} with {@link T2_PointerStorage} instance and pointer pointer + */ + @Test + public void chapter01() throws Exception { + Assert.assertEquals(false, T2_PointerStorage.usesNativeCode()); + + final Bindingtest2 bt2 = new Bindingtest2Impl(); + final T2_PointerStorage store = bt2.createT2PointerStorage(); + // final T2_PointerStorage store = T2_PointerStorage.create(); + final long[] int32PtrArray = store.getInt32PtrArray(0, new long[10], 0, 10); // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + { + Assert.assertEquals(10, int32PtrArray.length); + System.err.print("int32PtrArray[10] = { "); + for(int i=0; i<int32PtrArray.length; ++i) { + Assert.assertNotEquals(0, int32PtrArray[i]); + final ElementBuffer eb = ElementBuffer.derefPointer(Buffers.SIZEOF_INT, int32PtrArray[i], 1); + final IntBuffer ib = eb.getByteBuffer().asIntBuffer(); + Assert.assertEquals(1, ib.limit()); + final int value = ib.get(0); + Assert.assertEquals(i, value); + System.err.print(value+", "); + } + System.err.println("}"); + } + Assert.assertEquals(0, store.getInt32PtrPtrElemCount()); + store.setInt32PtrPtr(false, int32PtrArray, 3, 0, 7); // -> 3, 4, 5, 6, 7, 8, 9 + store.setInt32PtrPtr(true, int32PtrArray, 8, 3, 2); // -> 3, 4, 5, 8, 9, 8, 9 + store.setInt32PtrPtr(true, int32PtrArray, 0, 5, 2); // -> 3, 4, 5, 8, 9, 0, 1 + final long[] int32PtrPtr = store.getInt32PtrPtr(0, new long[7], 0, 7); // 3, 4, 5, 8, 9, 0, 1 + { + System.err.print("int32PtrPtr[7] = { "); + for(int i=0; i<int32PtrPtr.length; ++i) { + Assert.assertNotEquals(0, int32PtrPtr[i]); + final ElementBuffer eb = ElementBuffer.derefPointer(Buffers.SIZEOF_INT, int32PtrPtr[i], 1); + final IntBuffer ib = eb.getByteBuffer().asIntBuffer(); + Assert.assertEquals(1, ib.limit()); + final int value = ib.get(0); + final int exp; + switch( i ) { + case 0: exp = 3; break; + case 1: exp = 4; break; + case 2: exp = 5; break; + case 3: exp = 8; break; + case 4: exp = 9; break; + case 5: exp = 0; break; + case 6: exp = 1; break; + default: exp = 99; + } + Assert.assertEquals(exp, value); + System.err.print(value+", "); + } + System.err.println("}"); + } + bt2.destroyT2PointerStorage(store); + } + + public static void main(final String args[]) throws IOException { + final String tstname = Test3PtrStorage.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 75eafcf..e5c1fe2 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.c @@ -1,9 +1,14 @@ -#include "test2.h" - +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +typedef struct { + int value; +} T2_UndefStruct; + +#include "test2.h" + static int32_t CustomFuncA1(void* aptr) { (void)aptr; return 0xa001; @@ -33,6 +38,8 @@ int Initialize(T2_InitializeOptions* Options) { *( (T2_CustomFuncA*) &Options->CustomFuncA2 ) = CustomFuncA2; // yuck: real yuck Options->CustomFuncB1 = CustomFuncB1; Options->CustomFuncB2 = CustomFuncB2; + Options->customFuncBVariants[0] = CustomFuncB1; + Options->customFuncBVariants[1] = CustomFuncB2; Options->OverrideThreadAffinity = NULL; } @@ -52,4 +59,31 @@ int Release(T2_InitializeOptions* Options) { Options->CustomFuncB2 = NULL; } +static int32_t StaticInt32Array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +static T2_UndefStruct StaticUndefStructArray[] = { { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 } }; + +T2_PointerStorage * createT2PointerStorage() { + T2_PointerStorage * s = calloc(1, sizeof(T2_PointerStorage)); + for(int i=0; i<10; ++i) { + s->int32PtrArray[i] = &StaticInt32Array[i]; + } + s->undefStructPtr = &StaticUndefStructArray[0]; + for(int i=0; i<10; ++i) { + s->undefStructPtrArray[i] = &StaticUndefStructArray[i]; + } + + for(int i=0; i<10; ++i) { + s->customFuncAVariantsArray[i] = ( i %2 == 0 ) ? CustomFuncA1 : CustomFuncA2; + } + for(int i=0; i<10; ++i) { + s->customFuncBVariantsArray[i] = ( i %2 == 0 ) ? CustomFuncB1 : CustomFuncB2; + } + return s; +} + +void destroyT2PointerStorage(T2_PointerStorage * s) { + assert(NULL!=s); + memset(s, 0, sizeof(T2_PointerStorage)); + free(s); +} 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 7c31341..d40ac9a 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg @@ -20,7 +20,10 @@ ForceProcAddressGen __ALL__ # LocalProcAddressCallingConvention __ALL__ MYAPIENTRY Opaque long void* -Opaque long T2_Anonymous* + +# Undefined struct forward declaration, implementation secret: 'struct T2_UndefStruct;' +Opaque long T2_UndefStruct* +Ignore T2_UndefStruct EmitStruct T2_ThreadAffinity StructPackage T2_ThreadAffinity com.jogamp.gluegen.test.junit.generation @@ -29,6 +32,9 @@ EmitStruct T2_UserData StructPackage T2_UserData com.jogamp.gluegen.test.junit.generation ReturnsStringOnly T2_UserData.name +EmitStruct T2_PointerStorage +StructPackage T2_PointerStorage com.jogamp.gluegen.test.junit.generation + EmitStruct T2_InitializeOptions StructPackage T2_InitializeOptions com.jogamp.gluegen.test.junit.generation ReturnsStringOnly T2_InitializeOptions.ProductName @@ -40,6 +46,7 @@ MaxOneElement T2_InitializeOptions.OverrideThreadAffinity CustomCCode #include "test2.h" Import com.jogamp.gluegen.test.junit.generation.Bindingtest2 +Import com.jogamp.gluegen.test.junit.generation.T2_PointerStorage 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 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 0817dd9..75c7ffa 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.h @@ -2,24 +2,44 @@ #include <gluegen_stdint.h> #include <gluegen_stddef.h> -typedef struct T2_Anonymous* T2_AnonPtr; +// Opaque long T2_UndefStruct* +// struct T2_UndefStruct; // undefined struct forward declaration, implementation secret +typedef struct T2_UndefStruct* T2_UndefStructPtr; -typedef struct { - int32_t ApiVersion; - uint64_t NetworkWork; - T2_AnonPtr anonPtr; -} T2_ThreadAffinity; +typedef int32_t ( * T2_CustomFuncA)(void* aptr); typedef struct { 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 { + int32_t* int32PtrArray[10]; + int32_t** int32PtrPtr; + + T2_UndefStructPtr undefStructPtr; + T2_UndefStructPtr undefStructPtrArray[10]; + T2_UndefStructPtr* undefStructPtrPtr; + const T2_UndefStructPtr* constUndefStructPtrPtr; + + T2_CustomFuncA customFuncAVariantsArray[10]; + T2_CustomFuncA* customFuncAVariantsArrayPtr; + + T2_CustomFuncB customFuncBVariantsArray[10]; + T2_CustomFuncB* customFuncBVariantsArrayPtr; +} T2_PointerStorage; + +T2_PointerStorage * createT2PointerStorage(); +void destroyT2PointerStorage(T2_PointerStorage * s); + +typedef struct { + int32_t ApiVersion; + uint64_t NetworkWork; +} T2_ThreadAffinity; + +typedef struct { const char* ProductName; const char* ProductVersion; @@ -30,9 +50,16 @@ typedef struct { const T2_CustomFuncA CustomFuncA2; T2_CustomFuncB CustomFuncB1; T2_CustomFuncB CustomFuncB2; + T2_CustomFuncB customFuncBVariants[2]; T2_ThreadAffinity* OverrideThreadAffinity; } T2_InitializeOptions; extern int Initialize(T2_InitializeOptions* Options); extern int Release(T2_InitializeOptions* Options); + +typedef int32_t ( * T2_CallbackFunc)(size_t id, size_t msg_len, const char* msg, void* userParam); + +void AddMessageCallback(T2_CallbackFunc func, void* userParam); +void RemoveMessageCallback(T2_CallbackFunc func, void* userParam); +void InjectMessageCallback(size_t id, size_t msg_len, const char* msg); |