-
Notifications
You must be signed in to change notification settings - Fork 6
Declaring Java Types
Raw JNI provides very little in the way of type safety. There are jobject
, jstring
and a few other predefined types but most of the time you are on your own. Pretty much everything is jobject
and if you mix up OneJavaType with AnotherJavaType because of that - prepare to deal with runtime crash.
SimpleJNI rectifies this by requiring you to declare all Java types being used, either in JNI methods you implement or in Java methods/fields you access. Fortunately this is a very simple process. You declare a non-array (a.k.a.) Java type like this
DEFINE_JAVA_TYPE(jSomething, "com.mystuff.Something");
The first argument is the name of the C++ pointer type to create to represent the Java class. The second is the fully qualified name of the Java class. How to name the C++ type is up to you. In this guide we will follow jJavaSimpleName
convention. Note that jSomething
is a pointer type, just like jobject
is.
The declaration above should be put in the global namespace and the C++ type is created in global namespace. In the future we might expose a way to declare it in a namespace of your choosing.
The fully qualified name of a nested Java class is simply com.mystuff.Something$Nested
. That is, use $ sign to separate nested types from their owners.
Arrays are first class objects in Java so to use arrays you need to also declare a C++ representation. Don't forget to declare the element type first if you haven't done so!
DEFINE_JAVA_TYPE(jSomething, "com.mystuff.Something");
DEFINE_ARRAY_JAVA_TYPE(jSomething); //Declares jSomethingArray
The second line in the code above declares a jSomethingArray type. The Array suffix mimics the built-in JNI's jintArray
etc. and currently cannot be changed.
Java knows that a HashMap instance can be cast to Map but if we simply declare
DEFINE_JAVA_TYPE(jHashMap, "java.util.HashMap");
DEFINE_JAVA_TYPE(jMap, "java.util.Map");
the C++ side has no idea that a jHashMap
can be converted to jMap
. All such types automatically convert to jobject
(the 'pointed to' type inherits from the 'posted to' type of jobject
). However, due to a the way JNI works it is impossible to use inheritance to do the same for arbitrary types. Instead you tell SimpleJNI that two Java types are convertible explicitly
DEFINE_JAVA_CONVERSION(jHashMap, jMap);
The order of arguments isn't important. It simply allows conversion both ways using jstatic_cast
(note the j!) method or automatically for smart pointers.
jMap jm = ...;
jHashMap jhm = jstatic_cast<jHashMap>(jm);
local_java_ref<jMap> lrm = ...;
local_java_ref<jHashMap> lrhm = lrm; //succeeds with no casts
The syntax of jstatic_cast
is meant to closely resemble that of static_cast
of course. In practice you will fin that most of the time you will work with smart pointers so manual casts are unnecessary.
- Building
-
User's Guide
Declaring Java Types
Accessing Methods and Fields
Representing Java Classes
Implementing Native Methods
Smart References
Error Handling
Obtaining JNIEnv
Initialization
Strings
Arrays
Direct Buffers
Booleans
Sizes -
JniGen Code Generator
Integrating JniGen
Annotations
Processor Options