'Can I create a c++ class instance and use it as an entity in Android JNI?
Let's say I create a class 'Car' in cpp. I want to creat an instance of that class with it's empty constructor in cpp. Can I do it and use it in java code on android?
For instance:
Java code
Car myCar = new Car();
CPP class
class Car{
std::string model;
int creationYear;
Car(){}
}
thanks for the help
Solution 1:[1]
Yes. You can easily have a native object that shadows a Java object - assuming you can call the C++ Car() constructor. You could use a public static method in the C++ Car class to do that.
It's a bit of a hack, but a Java long is guaranteed to be 64 bits, so it's long enough to hold a native pointer value.
In Java:
public class Car
{
// A Java long is 64 bits, so it will
// hold a native pointer
private long nativeCar;
private native long newNativeCar();
private native void deleteNativeCar( long car );
public Car()
{
this.nativeCar = newNativeCar();
}
// allow for explicit native cleanup by caller
public synchronized deleteCar()
{
if ( 0 != this.nativeCar )
{
deleteNativeCar( nativeCar );
nativeCar = 0;
}
}
// handle cases where the native cleanup code
// was not called
@Override
protected void finalize() throws Throwable
{
deleteCar();
super.finalize();
}
}
Compile that, then use javah on the class file to create your C header file. (Note that JNI uses C, not C++. You can write C++ code to implement your logic, but the interface presented to the JVM must be a C interface.)
You'll get a couple of functions in your native header, something like this (I've stripped off the annotation from javah - you will need to keep that...):
jlong some_class_path_newNativeCar( JNIEnv *, jobject );
void some_class_path_deleteNativeCar( JNIEnv *, jobject, jlong );
You can implement your C++ code then:
jlong some_class_path_newNativeCar(
JNIEnv *env, jobject obj )
{
Car *nativeCar = new Car();
// C cast - we're returning a C value
return( ( jlong ) nativeCar );
}
void some_class_path_deleteNativeCar(
JNIEnv *env, jobject obj, jlong jNativeCar )
{
Car *cppNativeCar = ( Car * ) jNativeCar;
delete cppNativeCar;
}
I've deliberately kept the code simple - there's quite a bit I left out. javah can be a bit tricky to figure out how to use properly, for example. But if you can't figure out how to use javah properly you shouldn't be writing JNI code anyway.
Because JNI code is fragile. You can't make any mistakes, or you will wind up getting seemingly random failures or having your JVM crash, and the crash will likely not be easily traced to the bad code that caused the problem. There are lots of rules for making JNI calls using the JNIEnv * pointer supplied to a native call. For example, in general you can't save the values passed to you by the JVM and use them outside of the context you received them in - using them in another thread, or after the function where they were passed to you returns is a great way to cause those JVM crashes I mentioned above.
Nor can you make any JNI calls to Java if there are any exceptions pending from previous calls - again, you risk unpredictable errors and crashes if you do.
So keep your native code simple.
Keep all the logic and processing on only one side of the Java/native interface if you can.
Pass only C or Java strings, primitives or primitive arrays across the Java/native interface if you can.
Interacting with actual complex Java object from native code will take many, many lines of C or C++ code to safely replicate what can be done in Java with one or two lines of code. Even simple one-line get*()/set*() Java calls become 20 or 30 lines or more of C or C++ code if you replicate all the exception and failure checks you need in order to guarantee safe JVM execution after the native call no matter what data gets passed in. If you pass null to a Java method that can't handle a null value it will throw a NullPointerException that you can catch and your JVM runs happily or shuts down cleanly with an uncaught exception. Pass NULL to a JNI function that can't handle it, and if you don't properly check for any failure or any exception and then properly handle it, your JVM will exhibit seemingly unrelated failures or just crash.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
