2012-02-16 13 views
4

私はこれに固執しています。私はc/C++からJava関数を呼び出す必要があります。cからJava関数を呼び出す方法

例とチュートリアルでは、私はcメソッドを呼び出すjavaアプリケーションを見ています。この同じメソッドでは別のJavaメソッドを呼び出しますが、コードのどの部分からでもJavaメソッドを呼び出すだけです。

static JNIEnv mEnv; 
static jclass mClassAndroidActivity; 
static mMethodSayHello; 
JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) 
{ 
    mEnv = env; 
    jclass cls = (*env)->GetObjectClass(env, obj); 
    mClassAndroidActivity = (*env)->NewGlobalRef(env, cls); 
    mMethodSayHello = (*env)->GetMethodID (env, mClassAndroidActivity, "SayHello", "(Ljava/lang/String;)V"); 
} 

//this method is called from a cpp 
void nativeSayHello(char* msg) 
{ 
    jstring string = (*mEnv)->NewStringUTF(mEnv, msg); 
    (*mEnv)->CallVoidMethod(mEnv, mClassAndroidActivity, mMethodSayHello, string); 
} 

が、常にクラッシュし、私が代わりにJNI_Function内のenvのmEnvを使用して、NewGlobalRefせずに試してみたさに、私がJNI_OnLoadからメソッドIDを取得しようとしましたが、常にクラッシュ:これは私が持っているものです。 09::

2月15日18:48.520:dalvikvm/W(27904):JNI WARNING:スレッドID = 0

+0

'スレッド1からのenvがスレッド0とは違うと言われる「最良の」ログ'これは正しいと私は信じている。 Javaスレッドごとに異なるenvポインターが必要です。 – Yourpalal

+0

ええ、私は別のスレッドで使用することができるように最初のenvポインタを保存することができます –

答えて

9

することができます」からスレッドID = 1使用のenv

この

は私が取得ログです呼び出すスレッドに固有のものであるため、 JNIEnvを再利用しないでください。このコードスニペットがテストされていない

static JavaVM *gJavaVM; 
static jobject gCallbackObject = NULL; 

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { 
    gJavaVM = vm; 
    return JNI_VERSION_1_6; 
} 

JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) { 
    // ... 
    gCallbackObject = (*env)->NewGlobalRef(env, obj); 
} 

JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeRelease)(JNIEnv* env, jobject obj) { 
    (*env)->DeleteGlobalRef(env, gCallbackObject); 
    gCallbackObject = NULL; 
} 

//this method is called from native code 
void nativeSayHello(char* msg) { 
    int status; 
    JNIEnv *env; 
    int isAttached = 0; 

    if (!gCallbackObject) return; 

    if ((status = (*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { 
     if ((status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { 
      return; 
     } 
     isAttached = 1; 
    } 

    jclass cls = (*env)->GetObjectClass(env, gCallbackObject); 
    if (!cls) { 
     if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); 
     return; 
    } 

    jmethodID method = (*env)->GetMethodID(env, cls, "SayHello", "(Ljava/lang/String;)V"); 
    if (!method) { 
     if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); 
     return; 
    } 

    jstring string = (*mEnv)->NewStringUTF(mEnv, msg); 
    (*env)->CallVoidMethod(env, gCallbackObject, method, string); 

    if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); 
} 

:ネイティブコードから(非静的)Javaメソッドを呼び出すには、このようなものが必要。メモリリークを防ぐため、オブジェクトへの参照が必要なくなったときに、JavaコードでnativeRelease()メソッドを呼び出すことを忘れないでください。

詳細については、The Java Native Interfaceのマニュアルを参照してください。

+0

素晴らしい、それはthnxを動作させる –

+0

これはすごくうれしく..これはありがとう! – Bruce

関連する問題