Этот вопрос очень похож на этот
Вот мое решение для сохранения объектов на C ++, чтобы ссылаться на них из нескольких вызовов JNI:
Java
На стороне Java я создаю класс с указателем long
, чтобы сохранить ссылку на объект C ++.Оборачивая методы C ++ в класс Java, мы можем использовать методы C ++ в нескольких действиях.Обратите внимание, что я создаю объект C ++ в конструкторе и удаляю объект при очистке.Это очень важно для предотвращения утечек памяти:
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 ++
На стороне C ++ я определяю функции для создания, изменения и удаления объекта,Важно отметить, что мы должны использовать new
и delete
для хранения объекта в памяти HEAP, чтобы поддерживать его в течение всего жизненного цикла экземпляров класса Java.Я также храню указатель на CppObject
прямо в JavaClass
, используя getFieldId
, SetLongField
и 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;
}
}
ПРИМЕЧАНИЯ:
- В отличие от Java, C ++ не имеет сборки мусора, и объект будет жить в памяти HEAP, пока вы не используете
delete
. - Я использую
GetFieldID
, SetLongField
и GetLongField
для хранения ссылки на объект из C ++, но вы также можете хранить указатель на объект jlong
из Java, как обсуждалось в других ответах. - В моем конечном коде я реализовал класс
JavaObject
как Parcelable
, чтобы передать мой класс нескольким занятиям, используя Intent
с дополнительными функциями.