2016-08-16 4 views
1

私は自分のCコードから呼び出さなければならない関数を持つJavaクラスを持っています。 機能以下の通りです: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ポインタを格納することはできません。 Isは現在のスレッドに対してのみ有効です。
AttachCurrentThreadを使用すると、現在のスレッドのポインタJNIEnvを取得できます。
既に添付されていることがわかっている場合は、GetEnvを使用できます。
また、グローバルjobject objの使用方法については言及していませんが、それらの参照が有効であることに注意する必要があることに注意してください。 NewGlobalRefは行く方法です。

未テスト:あなたの返信用

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

おかげで私はjオブジェクトを使用する方法を示すために私のinitJNI関数内のコードの欠けている部分を追加しました。私の例でそれを使用する方法を示すためにコードを投稿することもできますか? – LBes

+0

@LBes:これはこのようにすべきだと思います。私はあなたの例を完全に理解していません。新しいオブジェクトを作成しようとしているようですが、オブジェクトも保存しているようです。そして、あなたの 'NewObject'呼び出しはCtorメソッドrefではありません。だからこれは疑わしい。しかし、私はこれが役立つことを願っています – mkaes

+0

あなたのコードをありがとう、私はこれをすぐに把握しようとしています。しかし、コード内のあなたのコメントに「グローバルを使用する」とはどういう意味ですか? – LBes