summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Féry <[email protected]>2023-06-15 18:03:13 +0200
committerMathieu Féry <[email protected]>2023-06-16 11:44:42 +0200
commitd7bc10d7ff0e3a30d74c4e4c439230f3983bcfb4 (patch)
tree4b0d789720c79cfb7604fd5107971c52814470e4
parent88309192b450e09ba16e9d72adac178c4ce47dc3 (diff)
feat(jni): Add directive for dedicated JNI Code with CustomJNICode
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java38
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java20
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java4
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test1p1JavaEmitter.java8
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2DynamicLibraryBundle.java8
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/Test1p2ProcAddressEmitter.java8
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJNICode.cfg13
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1-CustomJavaCode.cfg5
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg3
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.h2
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