diff options
author | Mathieu Féry <[email protected]> | 2023-06-15 18:03:13 +0200 |
---|---|---|
committer | Mathieu Féry <[email protected]> | 2023-06-16 11:44:42 +0200 |
commit | d7bc10d7ff0e3a30d74c4e4c439230f3983bcfb4 (patch) | |
tree | 4b0d789720c79cfb7604fd5107971c52814470e4 | |
parent | 88309192b450e09ba16e9d72adac178c4ce47dc3 (diff) |
feat(jni): Add directive for dedicated JNI Code with CustomJNICode
10 files changed, 108 insertions, 1 deletions
diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java index f392525..3241d83 100644 --- a/src/java/com/jogamp/gluegen/JavaConfiguration.java +++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java @@ -165,6 +165,7 @@ public class JavaConfiguration { private final Set<String> manuallyImplement = new HashSet<String>(); private final Map<String, String> delegatedImplementation = new HashMap<String, String>(); private final Map<String, List<String>> customJavaCode = new HashMap<String, List<String>>(); + private final Map<String, List<String>> customJNICode = new HashMap<String, List<String>>(); private final Map<String, List<String>> classJavadoc = new HashMap<String, List<String>>(); private final Map<String, List<String>> methodJavadoc = new HashMap<String, List<String>>(); private final Map<String, String> structPackages = new HashMap<String, String>(); @@ -601,6 +602,19 @@ public class JavaConfiguration { return res; } + /** Returns a list of Strings containing user-implemented JNI code for + the given Java type name (not fully-qualified, only the class + name); returns either null or an empty list if there is no + custom code for the class. */ + public List<String> customJNICodeForClass(final String className) { + List<String> res = customJNICode.get(className); + if (res == null) { + res = new ArrayList<String>(); + customJNICode.put(className, res); + } + return res; + } + public List<String> javadocForMethod(final String methodName) { List<String> res = methodJavadoc.get(methodName); if (res == null) { @@ -1330,6 +1344,10 @@ public class JavaConfiguration { } else if (cmd.equalsIgnoreCase("CustomCCode")) { readCustomCCode(tok, filename, lineNo); // Warning: make sure delimiters are reset at the top of this loop + // because readCustomJNICode changes them. + } else if (cmd.equalsIgnoreCase("CustomJNICode")) { + readCustomJNICode(tok, filename, lineNo); + // Warning: make sure delimiters are reset at the top of this loop // because readCustomCCode changes them. } else if (cmd.equalsIgnoreCase("MethodJavadoc")) { readMethodJavadoc(tok, filename, lineNo); @@ -1697,6 +1715,26 @@ public class JavaConfiguration { } } + protected void readCustomJNICode(final StringTokenizer tok, final String filename, final int lineNo) { + try { + final String tokenClassName = tok.nextToken(); + try { + final String restOfLine = tok.nextToken("\n\r\f"); + addCustomJNICode(tokenClassName, restOfLine); + } catch (final NoSuchElementException e) { + addCustomJNICode(tokenClassName, ""); + } + } catch (final NoSuchElementException e) { + throw new RuntimeException("Error parsing \"CustomJNICode\" command at line " + lineNo + + " in file \"" + filename + "\"", e); + } + } + + protected void addCustomJNICode(final String className, final String code) { + final List<String> codeList = customJNICodeForClass(className); + codeList.add(code); + } + protected void readMethodJavadoc(final StringTokenizer tok, final String filename, final int lineNo) { try { final String tokenClassName = tok.nextToken(); diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index ada1ce9..733f12a 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -830,7 +830,7 @@ public class JavaEmitter implements GlueEmitter { // Note that machDescJava MachineDataInfo is always 64bit unix, // which complies w/ Java types. - boolean needsNativeCode = false; + boolean needsNativeCode = !cfg.customJNICodeForClass(containingJTypeName).isEmpty(); // Native code for calls through function pointers gets emitted // into the abstract base class; Java code which accesses fields @@ -1162,6 +1162,7 @@ public class JavaEmitter implements GlueEmitter { javaUnit.emitln("}"); javaUnit.close(); if (needsNativeCode) { + emitCustomJNICode(jniUnit, containingJTypeName); jniUnit.close(); } if( GlueGen.debug() ) { @@ -2524,6 +2525,23 @@ public class JavaEmitter implements GlueEmitter { unit.emitln(" // ---- End CustomJavaCode .cfg declarations"); } + /** + * Emit all the strings specified in the "CustomJNICode" parameters of + * the configuration file. + */ + protected void emitCustomJNICode(final CodeUnit unit, final String className) throws Exception { + final List<String> code = cfg.customJNICodeForClass(className); + if (code.isEmpty()) + return; + + unit.emitln(); + unit.emitln(" // --- Begin CustomJNICode .cfg declarations"); + for (final String line : code) { + unit.emitln(line); + } + unit.emitln(" // ---- End CustomJNICode .cfg declarations"); + } + public String[] getClassAccessModifiers(final String classFQName) { String[] accessModifiers; final MethodAccess acc = cfg.accessControl(classFQName); diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java index ed23f54..276b585 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java @@ -2256,4 +2256,8 @@ public class BaseClass extends SingletonJunitCase { model.setCtx(surfaceContext); assertAPTR(surfaceContext, model.getCtx()); } + + public void chapter14TestCustomJNICode(final Bindingtest1 binding) throws Exception { + Assert.assertEquals(Bindingtest1.FOO_VALUE, binding.getFoo()); + } } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java index 3e19232..c7c5644 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java @@ -165,6 +165,14 @@ public class Test1p1JavaEmitter extends BaseClass { chapter15TestTKMixed(new Bindingtest1p1Impl()); } + /** + * Test Custom JNI Code invocation + */ + @Test + public void chapter14TestCustomJNICode() throws Exception { + chapter14TestCustomJNICode(new Bindingtest1p1Impl()); + } + public static void main(final String args[]) throws IOException { final String tstname = Test1p1JavaEmitter.class.getName(); org.junit.runner.JUnitCore.main(tstname); diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2DynamicLibraryBundle.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2DynamicLibraryBundle.java index def7655..e4adce1 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2DynamicLibraryBundle.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2DynamicLibraryBundle.java @@ -174,6 +174,14 @@ public class Test1p2DynamicLibraryBundle extends BaseClass { } /** + * Test Custom JNI Code invocation + */ + @Test + public void chapter14TestCustomJNICode() throws Exception { + chapter14TestCustomJNICode(new Bindingtest1p2Impl()); + } + + /** * Verifies unloading of the new library. */ @AfterClass diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java index 711f218..366d9eb 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java @@ -175,6 +175,14 @@ public class Test1p2ProcAddressEmitter extends BaseClass { } /** + * Test Custom JNI Code invocation + */ + @Test + public void chapter14TestCustomJNICode() throws Exception { + chapter14TestCustomJNICode(new Bindingtest1p2Impl()); + } + + /** * Verifies unloading of the new library. */ @AfterClass diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJNICode.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJNICode.cfg new file mode 100644 index 0000000..b76997d --- /dev/null +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJNICode.cfg @@ -0,0 +1,13 @@ +#include "test1.h" + +JNIEXPORT jobject JNICALL +com.jogamp.gluegen.test.junit.generation +Java_com_jogamp_gluegen_test_junit_generation_Bindingtest1p1_I_returnFooImpl(JNIEnv *env, jobject _unused) { + return FOO_VALUE; +} + +JNIEXPORT jobject JNICALL +com.jogamp.gluegen.test.junit.generation +Java_com_jogamp_gluegen_test_junit_generation_Bindingtest1p2_I_returnFooImpl(JNIEnv *env, jobject _unused) { + return FOO_VALUE; +}
\ No newline at end of file diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJavaCode.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJavaCode.cfg index 8d8f650..c210ec9 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJavaCode.cfg +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJavaCode.cfg @@ -4,4 +4,9 @@ public int testDelegate(int v) { return testDelegateOrigImpl(v) + 1; } +private native int returnFooImpl(); + +public int getFoo() { + return returnFooImpl(); +}; diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg index 7e9ba4a..e01f748 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg @@ -47,8 +47,11 @@ RenameJavaSymbol DEFINE_01_EXT DEFINE_01 RenameJavaSymbol testXID_EXT testXID DelegateImplementation testDelegate testDelegateOrigImpl +CustomJavaCode Bindingtest1 public int getFoo(); IncludeAs CustomJavaCode Bindingtest1p1Impl test1-CustomJavaCode.cfg +IncludeAs CustomJNICode Bindingtest1p1Impl test1-CustomJNICode.cfg IncludeAs CustomJavaCode Bindingtest1p2Impl test1-CustomJavaCode.cfg +IncludeAs CustomJNICode Bindingtest1p2Impl test1-CustomJNICode.cfg StructPackage TK_Dimension com.jogamp.gluegen.test.junit.generation EmitStruct TK_Dimension diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h index 89848d7..a296585 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h @@ -36,6 +36,8 @@ typedef void * XID; // Opaque typedef XID XID_2; // Opaque, due to XID typedef void * AnonBuffer; // Non Opaque +#define FOO_VALUE 42 + // typedef XID XID_2; // Duplicate w/ compatible type (ignored) - OpenSolaris: Native gcc error // typedef int XID_2; // Duplicate w/ incompatible type ERROR |