我的Java代码将调用现有的C++代码来解析文件。它将生成一个保存许多数据的对象。
我将调用jni的第二个方法来访问这些数据,
当我调用第二个方法时,我必须再次解析文件。这显然是正确的行为。
是否有一种处理方式? 顺便说一下:我是新手C++开发者。
是否有一种处理方式? 顺便说一下:我是新手C++开发者。
我不确定我是否正确理解了你的问题。但我猜你想做的是在多个jni调用中保持某种c++对象的存活。
你可以采取多种方法。首先解析你的文件并将c++对象存储在全局变量中。这是最简单的解决方案,但不是一种好的方案。
你也可以将c++对象的生命周期移到java中。
jlong java_some_class_jni_method(...)
{
.... parse your text file ....
MyParseclass* cls = new MyParseclass(...);
....
return (jlong) cls;
}
但请记住,您需要再次删除此本地C++类。因此,您需要一个JNI方法来执行此操作并确保调用它。
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
}
顺便说一句:如果您能发布一些代码,则会更有帮助。但我希望这里的伪代码能够稍微帮到您一点。
这个问题与这个问题非常类似。
以下是我为了从多个JNI调用中引用它们而保持C++对象存活的解决方案:
Java
在Java一侧,我正在创建一个具有long
指针的类,以保持对C++对象的引用。将C++方法封装在Java类中,允许我们在多个activity中使用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
来将对象存储在堆内存中,以便在整个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;
}
}
注意:
delete
删除。GetFieldID
、SetLongField
和GetLongField
来存储C++中的对象引用,但是您也可以像其他答案中讨论的那样存储Java的jlong
对象指针。JavaObject
类实现为一个Parcelable
,以便通过带有extras的Intent
传递我的类到多个活动中。