我的java代码将调用存在的c ++代码来解析文件。它会生成一个保存很多数据的对象。 我将调用jni的第二种方法来访问这些数据, 当我调用第二种方法时,我必须再次解析文件。这显然是正确的行为。
有办法解决这个问题吗? 顺便说一句:我刚接触c ++。
答案 0 :(得分:8)
我不确定我的问题是否正确。但我想你想要做的是在多个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
}
顺便说一句:如果你发布一些代码会更有帮助。但我希望这里的伪代码能有所帮助。
答案 1 :(得分:3)
此问题与this one
非常相似这是我在C ++上保持对象存活的解决方案,以便从多个JNI调用中引用它们:
<强>爪哇强>
在Java方面,我正在创建一个带有long
指针的类,以保持对C ++对象的引用。在Java类中包装C ++方法允许我们在多个活动中使用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;
}
}
备注:强>
delete
。GetFieldID
,SetLongField
和GetLongField
来存储来自C ++的对象引用,但您也可以存储来自Java的jlong
对象指针,如上所述其他答案。JavaObject
类作为Parcelable
实现,以便使用Intent
和其他内容将我的课程传递给多个活动。