2011-12-06 35 views
2

我的Java代码调用存在的C++代码来解析文件。它会生成一个保存许多数据的对象。 我将调用jni的第二种方法来访问这些数据, 当我调用第二种方法时,我必须再次解析文件。这显然是正确的行为。保持某种的C++对象在多个JNI调用活着

有没有办法来处理呢? 顺便说一句:我是新来的C++。

+0

我不知道你在问什么。你问是否有方法在C++中解析文件一次?答案肯定是。也许你可以解释你试图解决这个问题的方法以及你计算的问题。 –

+0

首先,我调用jni方法parseFile(); –

+0

第一,我调用JNI方法parseFile()(C++代码)和一些数据返回到Java。在这之后,accoridng用户的动作,例如触摸按钮,我会调用另一个JNI方法selectNote(),在第二JNI方法的C++代码,它将使用parseFile()产生的数据,所以必须调用parseFile()再次在selectNote()(C++代码)中。 –

回答

7

我不知道如果我理解你的问题是正确的。但我想你想要做的是保持某种C++对象在多个jni调用中存活。

你可以做很多事情。首先解析您的文件并将您的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 
} 

顺便说一句:如果你会张贴一些代码会更有帮助。但我希望这里的这个伪代码有所帮助。

+0

太好了。这就是我要的。我会尝试。 –

+0

我只是尝试,它的工作原理。 –

0

这个问题是非常相似的this one

这里是我的解决方案,以保持物体活在C++,以便从多个JNI引用它们来电:

的Java

在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++的一面,我定义函数来创建,修改和删除的对象。需要提及的是,我们必须使用newdelete将对象存储在HEAP内存中,以便在Java类实例的整个生命周期中保持活动状态。我也存储指针CppObject直在JavaClass,使用getFieldIdSetLongFieldGetLongField

// 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
  • 我使用GetFieldIDSetLongFieldGetLongField存储从C++对象引用,但你也可以在jlong对象的指针从Java软件商店上的其他答案的讨论。
  • 在我的最终代码上,我实施了JavaObject类作为Parcelable,以便将我的课程用Intent与其他课程一起传递给多个活动。