-
Notifications
You must be signed in to change notification settings - Fork 10
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 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 'pointed to' type of jobject). However, due to 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 castsThe syntax of jstatic_cast is meant to closely resemble that of static_cast of course. In practice you will find 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