2016-08-16 50 views
1

我有一個Java類,其中我有一個必須從我的C代碼中調用的函數。 的功能如下:JNI環境指針

public void endTrial(){ 
    //Code 
} 

所以我在我的C文件中創建下面的代碼:

JNIEXPORT void JNICALL package_endTrialJava(); 
JNIEXPORT void JNICALL package_endTrialJava(){ 
    jobject javaObjectRef = env->NewObject(javaClassRef, javaMethodRef); 
    env->CallVoidMethod(javaObjectRef, javaMethodRef); 
} 

但是爲了能夠調用與env變量這個功能,我創造了這個當我啓動我的程序時調用這個函數。

JNIEXPORT void JNICALL package_initJNI(JNIEnv* en, jobject ob) 
{ 
    try { 
     // LOGD("(JNI) [FluidMechanics] loadVelocityDataSet()"); 

     if (!App::getInstance()) 
      throw std::runtime_error("init() was not called"); 

     if (App::getType() != App::APP_TYPE_FLUID) 
      throw std::runtime_error("Wrong application type"); 


     FluidMechanics* instance = dynamic_cast<FluidMechanics*>(App::getInstance()); 
     android_assert(instance); 
     jclass dataClass = en->FindClass("fr/limsi/ARViewer/MainActivity"); 
     javaClassRef = (jclass) env->NewGlobalRef(dataClass); 
     javaMethodRef = env->GetMethodID(javaClassRef, "endTrial", "()V"); 

     env = en ; 
     obj = ob ;   

    } catch (const std::exception& e) { 
     throwJavaException(env, e.what()); 
    } 
} 

而且我在我的代碼中聲明,以及這些全局變量,從而使呼叫initJNI()可以存儲JNIEnv的變量。

JNIEnv* env ; 
jobject obj ; 

但我的程序崩潰,所以看起來存儲JNIEnv變量不起作用。是否有任何解決方法呢?

回答

2

您不能/不應該存儲JNIEnv指針。僅對當前線程有效。
但是,您可以使用AttachCurrentThread獲取當前線程的JNIEnv指針。
或者如果你知道它已經連接,你可以使用GetEnv
除此之外,你沒有提到你如何使用全球jobject obj,但請記住,你需要注意這些引用保持有效的時間足夠長。 NewGlobalRef是要走的路。

未經測試:你的答覆我添加的代碼的缺失的部分,我initJNI函數來顯示我如何使用jobject

JavaVM* g_jvm = 0; 
JNIEXPORT void JNICALL package_initJNI(JNIEnv* en, jobject ob) 
{ 
    .... 
    // insted of the env store the VM 
    en->GetJavaVM(&g_jvm); 
    obj = en->NewGlobalRef(ob); // I don't think you need this 
    // and at some point you must delete it again 
    .... 
} 

JNIEXPORT void JNICALL package_endTrialJava(){ 
    JNIEnv* env; 
    g_jvm->AttachCurrentThread(&env, NULL); // check error etc 
    jobject javaObjectRef = env->NewObject(javaClassRef, javaMethodRef); 
    // this line makes not much sense. I think you don't need it if you use the global 
    // with the global it would be more like this 
    env->CallVoidMethod(obj javaMethodRef); 
} 
+0

感謝。你可以發佈代碼以說明如何在我的例子中使用它? – LBes

+0

@LBes:我想應該是這樣的。我完全不瞭解你的例子。看起來你正在嘗試創建一個新的對象,但你也存儲一個對象。而你的'NewObject'call沒有Ctor方法參考。所以這看起來很可疑。但我希望這有助於。 – mkaes

+0

感謝您的代碼,我會盡力解決這個問題。但是,在代碼中的評論中,「使用全局」是什麼意思? – LBes