Android NDK,保持实时C++对象
我有以下问题。我想编写一个Android应用程序,它将我的旧C++类。我必须在整个应用程序生存期内保持C++对象处于活动状态。
我用C#编写了一个类似的应用程序,通过将指向C++类的指针传递给C#并使用IntPtr将其存储在那里来解决这个问题。然后,当我想在该对象上调用方法时,我只需再次将该指针传递给C++,转换为类指针并对其调用方法。
如何在 Java 和 Android NDK 中实现类似的结果?Java 是否支持存储指针?
我有以下问题。我想编写一个Android应用程序,它将我的旧C++类。我必须在整个应用程序生存期内保持C++对象处于活动状态。
我用C#编写了一个类似的应用程序,通过将指向C++类的指针传递给C#并使用IntPtr将其存储在那里来解决这个问题。然后,当我想在该对象上调用方法时,我只需再次将该指针传递给C++,转换为类指针并对其调用方法。
如何在 Java 和 Android NDK 中实现类似的结果?Java 是否支持存储指针?
是的,您可以执行与在 C# 中执行的操作完全相同的操作。
要创建新的C++对象:
jlong
Java_package_name_new(JNIEnv *, jobject) {
return (long)(new CPP_Object());
}
您可以将此方法的返回值存储在 Java 变量中,并将其传递给所有需要它的 NDK 方法:ptr
void
Java_package_name_doSomething(JNIEnv *, jobject, jlong ptr) {
CPP_Object *obj = (CPP_Object *)ptr;
// do whatever you want with the object
}
最后用下面这样的东西删除它:
void
Java_package_name_delete(JNIEnv *, jobject, jlong ptr) {
delete (CPP_Object *)(ptr);
}
除了传递给所有需要它的方法之外,您还可以使用 and 方法直接从 NDK 部分获取它并进行设置:这允许 Java 变量仅从代码的 NDK 部分进行管理,我发现该部分更安全、更易于管理。ptr
SetLongField
GetLongField
ptr
我对对话有点晚了,但由于我找不到一个完全回答这个问题的SO帖子,所以我会发布我的解决方案。
爪哇岛
在Java方面,我正在创建一个带有指针的类,以保留对C++对象的引用。将C++方法包装在Java类中,使我们能够在多个活动中使用C++方法。请注意,我正在构造函数上创建C++对象,并且在清理时删除该对象。这对于防止内存泄漏非常重要:long
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++方面,我正在定义用于创建,修改和删除对象的函数。值得一提的是,我们必须使用对象并将其存储在HEAP内存中,以使其在Java类实例的整个生命周期中保持活动状态。我还将指针存储在 、 使用 、 和 :new
delete
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;
}
}
笔记:
delete
GetFieldID
SetLongField
GetLongField
jlong
JavaObject
Parcelable
Intent