1. 程式人生 > >Jni 多執行緒程式設計,子執行緒回撥java方法

Jni 多執行緒程式設計,子執行緒回撥java方法

由於c++層接收到服務端主動推送tcp資料,所以存在將c++層接收到的socket資料通過層層回撥至java的需求。

以下為c++程式碼段:
1:在c++標頭檔案中定義申明相應回撥函式指標

typedef void (*SwitchStateChangeCallback)(char *pchar);//定義伺服器主動回撥函式
SwitchStateChangeCallback switchStateChangeCallback;//申明函式回撥

2:jni中實現相應回撥方法

void SwitchCallbackToJni(char *pchar) {
    LOGD("callback jni:%s",pchar);
    jclass jclassobj = threadEnv->GetObjectClass(gs_object);
    jmethodID method = threadEnv->GetMethodID(jclassobj,"swithDataCallback","(ZLjava/lang/String;)V");
    if(method == NULL)
    {
       LOGD("can't find Method swithDataCallback(boolean,String)");
    }
threadEnv->CallVoidMethod(gs_object,method,TRUE,CharTojstring(threadEnv,pchar)); }

3:在jni呼叫函式時將相應回撥函式設定至c++中

    smartSwitch = new SmartHomeSwitch();
    smartSwitch>setSwitchStateChangeCallback(SwitchCallbackToJni);

4:在c++程式碼適當位置回撥預存的jni方法
switchStateChangeCallback(pCharResponse); //回撥至jni層

注意問題

由於c++主動回撥是無法攜帶相應的jni env 和 jobect 主要為了不耦合,不希望在c++類中引入到jni相關的標頭檔案,所以只能回撥相應資料到jni層,交由jni自由處理,所以需要預先儲存好jniEnv 和 相應 的jclass,(如果存在多執行緒,並在子執行緒中呼叫回撥,主執行緒的jni env將不可用(執行緒獨立),此時需單獨獲取子執行緒中jni env指標,並在執行緒結束前釋放)

    int retGvm=env->GetJavaVM(&gs_jvm);//儲存jvm
    gs_object=env->NewGlobalRef(jObj);//儲存obj

執行緒內獲取與釋放jni env指標

void ThreadChangeJniCallback(bool isRun){
    if(isRun){
        gs_jvm->AttachCurrentThread(&threadEnv, NULL);//執行緒開始獲取
    }else{
        gs_jvm->DetachCurrentThread();//執行緒結束釋放
    }
}