I have a JNI class with methods init()
work()
, and cleanup()
. On the C++ side I create an instance of a C++ class Foo
during init()
, then call some methods on it during work()
, and finally delete it inside cleanup()
. Right now I store instance of Foo
as a global singleton on the C++ so that I can retrieve it from the different JNI calls. What I would really like to do is store a pointer to the Foo
instance inside the jobject
instance that gets passed to each JNI call, so that I can avoid having a global singleton and also so that I can support multiple instances of Foo
. Is something like this possible?
You can store a pointer to your C++ object as a Java class member. For example, in Java:
class Foo
{
public long ptr = 0;
public native void init();
public native void work();
public native void cleanup();
}
And in C++:
jfieldID getPtrFieldId(JNIEnv * env, jobject obj)
{
static jfieldID ptrFieldId = 0;
if (!ptrFieldId)
{
jclass c = env->GetObjectClass(obj);
ptrFieldId = env->GetFieldID(c, "ptr", "J");
env->DeleteLocalRef(c);
}
return ptrFieldId;
}
class Foo
{
/* ... */
};
extern "C"
{
void Java_Foo_init(JNIEnv * env, jobject obj)
{
env->SetLongField(obj, getPtrFieldId(env, obj), (jlong) new Foo);
}
void Java_Foo_work(JNIEnv * env, jobject obj)
{
Foo * foo = (Foo *) env->GetLongField(obj, getPtrFieldId(env, obj));
foo->work();
}
void Java_Foo_cleanup(JNIEnv * env, jobject obj)
{
Foo * foo = (Foo *) env->GetLongField(obj, getPtrFieldId(env, obj));
delete foo;
}
}