2008年1月18日 星期五

[Java] Registry a java callback method to any C++ task-thread

VMROk

Registry a java callback method to any C++ task-thread ...

Sometimes, in java application, we will launch a C++ working thread to do a high computing consuming job. When the job done, send a notification to the java application.

You can use a Message to finish the requirement.Also, you can use JNI to invoke any method of a java object that are referenced from the parameter jobject.

If you invoke the Java method in other thread in C++, you will face a problem! The JNI interface pointer (JNIEnv) is valid only in the current thread.If you want to access java object at other thread, you should use AttachCurrentThread to attach current thread to the java virtual machine.

 

How to use AttachCurrentThread in your code? An example is listed as following.

 

JNIEXPORT jint JNICALL Java_xxx(JNIEnv *env, jobject jobj, ...){

                   ...

       Data->jobj = env->NewGlobalRef(jobj);

      // 建立 c++ thread, 執行高耗時程序, 完成時, call back 到 java method

}

=============== Other C++ thread method ==============

      // Step 1: 目前的 JVM 取得 env 的範例

       JNIEnv* env;
        int bOk=curJavaVM->AttachCurrentThread((void**)&env, (void*) 0);
       

         // Step 2: 取得 jclass 和 method Id

// 注意:

        // 如果你的java callback 是 static method, 可以使用 FindClass

       // 例如:  jclass cls=env->FindClass("xxx/myclass");

        // 但是, 如果你呼叫的 java callback 是一般 method , 則

       // 請使用 GetObjectClass, 範例如下:  其中 jobj 為傳進來 jobject

        jclass cls=env->GetObjectClass(Data->jobj);


        jmethodID mid=env->GetMethodID(cls,"myfunction", "(I)V");
      

        // Step 3: 利用 env 呼叫 放在 java 物件中的 method

       env->CallVoidMethod(Data->jobj, mid, 123);
        if(env->ExceptionOccurred()) {
            printf("error occured on render2_callback method");
            env->ExceptionDescribe();
            env->ExceptionClear();
        }

       // Step 4: 因為 jobj 使用 NewGlobalRef , 所以記得移除 
        env->DeleteGlobalRef(Data->jobj);

 

 

其他程式

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)  
{   
    curJavaVM=vm; // 取得 目前vm
    return JNI_VERSION_1_2;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
{
}

 

 

by Jing

1 則留言:

  1. It is very interesting problem. Do you have the full source codes for this example? I appreciate it if you can post it online.

    回覆刪除