Merge: Java FFI: add GC pinning support
authorJean Privat <jean@pryen.org>
Mon, 9 Nov 2015 15:39:14 +0000 (10:39 -0500)
committerJean Privat <jean@pryen.org>
Mon, 9 Nov 2015 15:39:14 +0000 (10:39 -0500)
Adds a missing features to the Java FFI: pinning references to Nit objects from Java. Both services, `..._incr_ref` and `..._decr_ref`, are "simple" redirections from Java to the nitni service in C through the JNI.

Pull-Request: #1820
Reviewed-by: Jean Privat <jean@pryen.org>

src/ffi/java.nit
tests/sav/test_ffi_java_refs.res [new file with mode: 0644]
tests/test_ffi_java_refs.nit [new file with mode: 0644]

index eca32ac..1adb9c9 100644 (file)
@@ -220,6 +220,9 @@ redef class MModule
                for cb in callbacks do
                        jni_methods.add_all(cb.jni_methods_declaration(self))
                end
+               for cb in callbacks_used_from_java.types do
+                       jni_methods.add_all(cb.jni_methods_declaration(self))
+               end
 
                var cf = new CFunction("void nit_ffi_with_java_register_natives(JNIEnv* env, jclass jclazz)")
                cf.exprs.add """
@@ -470,6 +473,38 @@ redef class MType
        # Used by `JavaLanguage::compile_extern_method` when calling JNI's `CallStatic*Method`.
        # This strategy is used by JNI to type the return of callbacks to Java.
        private fun jni_signature_alt: String do return "Int"
+
+       redef fun compile_callback_to_java(mmodule, mainmodule, ccu)
+       do
+               var java_file = mmodule.java_file
+               if java_file == null then return
+
+               for variation in ["incr", "decr"] do
+                       var friendly_name = "{mangled_cname}_{variation}_ref"
+
+                       # C
+                       var csignature = "void {mmodule.impl_java_class_name}_{friendly_name}(JNIEnv *env, jclass clazz, jint object)"
+                       var cf = new CFunction("JNIEXPORT {csignature}")
+                       cf.exprs.add "\tnitni_global_ref_{variation}((void*)(long)object);"
+                       ccu.add_non_static_local_function cf
+
+                       # Java
+                       java_file.class_content.add "private native static void {friendly_name}(int object);\n"
+               end
+       end
+
+       redef fun jni_methods_declaration(from_mmodule)
+       do
+               var arr = new Array[String]
+               for variation in ["incr", "decr"] do
+                       var friendly_name = "{mangled_cname}_{variation}_ref"
+                       var jni_format = "(I)V"
+                       var cname = "{from_mmodule.impl_java_class_name}_{friendly_name}"
+                       arr.add """{"{{{friendly_name}}}", "{{{jni_format}}}", {{{cname}}}}"""
+               end
+
+               return arr
+       end
 end
 
 redef class MClassType
diff --git a/tests/sav/test_ffi_java_refs.res b/tests/sav/test_ffi_java_refs.res
new file mode 100644 (file)
index 0000000..422c2b7
--- /dev/null
@@ -0,0 +1,2 @@
+a
+b
diff --git a/tests/test_ffi_java_refs.nit b/tests/test_ffi_java_refs.nit
new file mode 100644 (file)
index 0000000..efab321
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import java
+
+class A
+       fun foo in "Java" `{
+               A_incr_ref(self);
+               System.out.println("a");
+               A_decr_ref(self);
+               System.out.println("b");
+       `}
+end
+
+var a = new A
+a.foo