簡體   English   中英

在GLSurcfaceView回調期間從C ++調用回Java的問題

[英]Issue calling back into Java from C++ called during a GLSurcfaceView callback

我在Android應用程序的JAR文件中創建了GLSurfaceView。 在onDrawFrame的GLSurfaceView回調中,我通過JNI調用了本機C ++方法。 在這一點上,我相信我在GLThread中,並且在該本機方法中,我試圖在我應用程序的名稱空間中調用Java類,而不是在進行調用的名稱空間中進行調用。 因此,我試圖在這樣做之前顯式地附加到UI線程,但是我沒有成功。

我收到以下錯誤

W/dalvikvm( 4243): JNI WARNING: can't call Lcom/main/myapp;.updateView on instance of Lorg/myorg/myRenderer;
W/dalvikvm( 4243):              in Lorg/myorg/ImageRenderer;.renderImageFrame:()V (CallVoidMethodV)
I/dalvikvm( 4243): "GLThread 336" prio=5 tid=16 RUNNABLE
I/dalvikvm( 4243):   | group="main" sCount=0 dsCount=0 obj=0x418029f8 self=0x400988a8
I/dalvikvm( 4243):   | sysTid=4268 nice=0 sched=0/0 cgrp=apps handle=1362099424
I/dalvikvm( 4243):   | schedstat=( 0 0 0 ) utm=83 stm=71 core=1
I/dalvikvm( 4243):   at org.myorg.ImageRenderer.renderImageFrame(Native Method)
I/dalvikvm( 4243):   at org.myorg.ImageRenderer.onDrawFrame(ImageRenderer.java:93)
I/dalvikvm( 4243):   at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
I/dalvikvm( 4243):   at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

我的C ++代碼如下所示:

JavaVM * jvm;

JNIEXPORT void JNICALL Java_org_myorg_ImageRenderer_renderImageFrame
  (JNIEnv *env, jobject jObj) {

 jvm->AttachCurrentThread(&env, 0);

        jclass javaClass = env->FindClass("com/main/myapp");
             if(javaClass == NULL){
                 LOGD("ERROR - CANNOT FIND CLASS");
             }

        jfloatArray viewArray = env->NewFloatArray(16);
        env->SetFloatArrayRegion(viewArray, 0, 16, glmatrix.data);
        jmethodID method = env->GetMethodID(javaClass, "updateView", "([F)V");
        if(method == NULL){
            LOGD("ERROR - CANNOT ACCESS METHOD");
        }

        env->CallVoidMethod(jObj, method, viewArray);
        env->DeleteLocalRef(viewArray);

jvm->DetachCurrentThread();

}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
    jvm = vm;
    return JNI_VERSION_1_2;
}

我正在嘗試在應用程序的命名空間中回調到Java類,而不是在進行調用的命名空間中回調

是的,就是這個問題。 你已經看過了放在methodIDcom.main.myapp但你試圖調用上的原jobject實例放在methodID org.myorg.ImageRenderer 如果要從另一個“命名空間”調用方法,則有以下幾種選擇:

  1. 該方法必須是靜態的,以便找到一個類就足夠了,並且您不需要對象
  2. 另一個對象必須在本機方法中作為參數傳遞
  3. 另一個對象必須作為原始對象的成員/獲取者(聲明了您的本機方法)才能訪問,然后可以通過JNI方法查找和調用來訪問

您的函數是從Java調用的,因此您不應調用AttachCurrentThread

您的函數從Java接收到對org.myorg.myRenderer對象的引用,該對象的renderImageFrame()是本機方法(每個本機方法都將Java環境env接收為第一個參數,其對象引用通常稱為thiz ,作為第二個參數參數。

如果你想調用Java方法的UpdateView()的app類的對象com.main.myapp ,你應該首先獲得該對象的引用。 最簡單的方法是將其作為參數傳遞給函數,因此現在將其聲明為

 JNIEXPORT void JNICALL Java_org_myorg_ImageRenderer_renderImageFrame(JNIEnv *env, jobject thiz, jobject app);

另外,如果對app的引用是org.myorg.myRenderer的字段,或者被此類的某些方法所破壞,則可以從thiz找到app對象。

最后,您可能是對的,從GL線程中調用需要UI線程的updateView()方法不是一個好主意。 您可能應該發布一個post ,或者發送一條消息,或者干脆調用runOnUIThread()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM