My java code will call the exist c++ code to parse the file. it will generate an object which keep many data. I will call the jni's second method to access such data, When I call the second method, I have to parse the file again. it is obviously the right behavior.
Is there a way to handle this ? BTW: I am newly to c++.
typedef jobject jclass; In C++, JNI introduces a set of dummy classes to enforce the subtyping relationship. For example: class _jobject {}; class _jclass : public _jobject {}; ...
jobject NewGlobalRef(JNIEnv *env, jobject obj); Creates a new global reference to the object referred to by the obj argument. The obj argument may be a global or local reference.
JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).
jobject thiz means the this in java class. Sometimes if you create a static native method like this. void Java_MyClass_method1 (JNIEnv *, jclass); jclass means the class itself. Follow this answer to receive notifications.
I am not sure if I understand your question correct. But I guess what you want to do is to keep some sort of c++ object alive over multiple jni calls.
You can do multiple things. First parse your file and store your c++ object in a global variable. This is the simplest solution but not a nice one.
You can also move the life cycle of your c++ object into java.
jlong java_some_class_jni_method(...)
{
.... parse your text file ....
MyParseclass* cls = new MyParseclass(...);
....
return (jlong) cls;
}
But keep in mind that you need to delete this native c++ class again. So you need a jni method to this and be sure to call it.
void java_some_calls_jni_method(..., jlong clsPtr)
{
MyParseclass* cls = (MyParseclass*)clsPtr;
... do maybe do something with cls and access the data...
delete cls; // do not use the jlong again in any call
}
BTW: It would be much more helpful if you would post some code. But I hope this pseudo code here helps a little.
This question is very similar to this one
Here's my solution to keeping objects alive on C++ in order to reference them from multiple JNI calls:
Java
On the Java side, I am creating a class with a long
pointer to keep a reference to the C++ object. Wrapping the C++ methods in a Java class, allows us to use the C++ methods in multiple activities. Notice that I am creating the C++ object on the constructor, and I am deleting the object on cleanup. This is very important in order to prevent memory leaks:
public class JavaClass {
// Pointer (using long to account for 64-bit OS)
private long objPtr = 0;
// Create C++ object
public JavaClass() {
createCppObject();
}
// Delete C++ object on cleanup
public void cleanup() {
deleteCppObject();
this.objPtr = 0;
}
// Native methods
public native void createCppObject();
public native void workOnCppObject();
public native void deleteCppObject();
// Load C++ shared library
static {
System.loadLibrary("CppLib");
}
}
C++
On the C++ side, I am defining functions to create, modify and delete the object. It's important to mention that we have to use new
and delete
to store the object in the HEAP memory to keep it alive throughout the lifecycle of the Java class instances. I am also storing the pointer to CppObject
straight in the JavaClass
, using getFieldId
, SetLongField
, and GetLongField
:
// Get pointer field straight from `JavaClass`
jfieldID getPtrFieldId(JNIEnv * env, jobject obj)
{
static jfieldID ptrFieldId = 0;
if (!ptrFieldId)
{
jclass c = env->GetObjectClass(obj);
ptrFieldId = env->GetFieldID(c, "objPtr", "J");
env->DeleteLocalRef(c);
}
return ptrFieldId;
}
// Methods to create, modify, and delete Cpp object
extern "C" {
void Java_com_test_jnitest_JavaClass_createCppObject(JNIEnv *env, jobject obj) {
env->SetLongField(obj, getPtrFieldId(env, obj), (jlong) new CppObject);
}
void Java_com_test_jnitest_JavaClass_workOnCppObject(JNIEnv *env, jobject obj) {
CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));
// Write your code to work on CppObject here
}
void Java_com_test_jnitest_JavaClass_deleteCppObject(JNIEnv *env, jobject obj) {
CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));
delete cppObj;
}
}
NOTES:
delete
.GetFieldID
, SetLongField
, and GetLongField
to store the object reference from C++, but you could also store the jlong
object pointer from Java as discussed on other answers.JavaObject
class as a Parcelable
in order to pass my class to multiple activities using Intent
with extras.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With