{{{block.code}}}
}
"""
+
+ mmodule.callbacks_used_from_java.join m.foreign_callbacks
end
redef fun compile_extern_class(block, m, ccu, mmodule) do end
mmodule.insert_compiler_options
# Enable linking C callbacks to java native methods
- mmodule.ensure_linking_callback_methods(ffi_ccu.as(not null), mmodule.ffi_callbacks[self])
+ mmodule.ensure_linking_callback_methods(ffi_ccu.as(not null))
# Java implementation code
var java_file = mmodule.java_file
end
redef class MModule
+ private var callbacks_used_from_java = new ForeignCallbackSet
# Pure java class source file
private var java_file: nullable JavaClassTemplate = null
end
# Compile C code to call JNI and link C callbacks implementations to Java extern methods
- private fun ensure_linking_callback_methods(ccu: CCompilationUnit, callbacks: Set[NitniCallback])
+ private fun ensure_linking_callback_methods(ccu: CCompilationUnit)
do
+ var callbacks = callbacks_used_from_java.callbacks
if callbacks.is_empty then
ccu.body_decl.add "static int nit_ffi_with_java_registered_natives = 1;\n"
return
jni_methods.add_all(cb.jni_methods_declaration(self))
end
- var cf = new CFunction("static void nit_ffi_with_java_register_natives(JNIEnv* env, jclass jclazz)")
+ var cf = new CFunction("void nit_ffi_with_java_register_natives(JNIEnv* env, jclass jclazz)")
cf.exprs.add """
nit_ffi_with_java_registered_natives = 1;
# Tell the C compiler where to find jni.h and how to link with libjvm
private fun insert_compiler_options
do
- c_compiler_options = "{c_compiler_options} -I $(JAVA_HOME)/include/"
- c_linker_options = "{c_linker_options} -L $(JNI_LIB_PATH) -ljvm"
+ cflags.add_one("", "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/")
+ ldflags.add_one("", "-L $(JNI_LIB_PATH) -ljvm")
end
# Name of the generated Java class where to store all implementation methods of this module
assert sys_class != null
var sys_jni_env_meth = modelbuilder.try_get_mproperty_by_name2(self, mmodule, sys_class.mclass_type, "jni_env")
if sys_jni_env_meth == null or not sys_jni_env_meth isa MMethod then
- toolcontext.error(self.location, "Java FFI error: you must import the `java` module when using the FFI with Java")
+ toolcontext.error(self.location, "Java FFI Error: you must import the `java` module when using the FFI with Java")
return
end
redef class MExplicitCall
redef fun compile_callback_to_java(mmodule, mainmodule, ccu)
do
+ if not mmodule.callbacks_used_from_java.callbacks.has(self) then return
+
var mproperty = mproperty
assert mproperty isa MMethod
else break
end
+ # Change `float[]` to `[float`
+ if jni_type.has('[') then
+ var depth = jni_type.chars.count('[')
+ var java_type = jni_type.replace("[]", "")
+ var short
+
+ if java_type == "boolean" then
+ short = "Z"
+ else if java_type == "byte" then
+ short = "B"
+ else if java_type == "char" then
+ short = "C"
+ else if java_type == "short" then
+ short = "S"
+ else if java_type == "int" then
+ short = "I"
+ else if java_type == "long" then
+ short = "J"
+ else if java_type == "float" then
+ short = "F"
+ else if java_type == "double" then
+ short = "D"
+ else
+ short = "L{java_type};"
+ end
+
+ return "["*depth + short
+ end
+
return "L{jni_type};"
end
if mclass.name == "Bool" then return "Z"
redef fun jni_signature_alt
do
var ftype = mclass.ftype
+
if ftype isa ForeignJavaType then return "Object"
if mclass.name == "Bool" then return "Boolean"
if mclass.name == "Char" then return "Char"