![](/img/trans.png)
[英]Calling a c++ callback from Java invoked from C++ application via JNI
[英]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類,而不是在進行調用的命名空間中回調
是的,就是這個問題。 你已經看過了放在methodID類com.main.myapp
但你試圖調用上的原jobject實例放在methodID org.myorg.ImageRenderer
! 如果要從另一個“命名空間”調用方法,則有以下幾種選擇:
您的函數是從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.