0

我在我的 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;
}
4

2 回答 2

4

我正在尝试回调到我的应用程序命名空间中的 Java 类,而不是调用调用的命名空间

是的,这就是问题所在。您在类中查找了一个methodIDcom.main.myapp ,但随后您尝试在!的原始jobject实例上调用该methodID 如果你想从另一个“命名空间”调用一个方法,你有几个选择:org.myorg.ImageRenderer

  1. 该方法必须是静态的,这样找到一个类就足够了,你不需要一个对象
  2. 另一个对象必须在本机方法中作为参数传递
  3. 另一个对象必须可以作为原始对象(声明您的本机方法)的成员/getter 访问,然后通过 JNI 方法查找和调用访问
于 2012-12-02T21:05:24.997 回答
0

您的函数是从 Java 调用的,因此您不应调用AttachCurrentThread.

您的函数从 Java 接收对org.myorg.myRenderer对象的引用,其中 renderImageFrame() 是本机方法(每个本机方法都接收 Java 环境env作为第一个参数,其对象引用,通常表示为thiz,作为第二个参数。

如果要为appclass 的对象调用 Java 方法 updateView() com.main.myapp,则应首先获取对该对象的引用。最简单的方法是将它作为参数传递给你的函数,所以现在它将被声明为

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

或者,如果对 的引用是 的字段,或者由此类的某些方法返回,则可以app从 中找到对象。thizapporg.myorg.myRenderer

最后,您可能是对的updateView(),从 GL 线程调用需要 UI 线程的方法并不是一个好主意。您可能应该发出post,或发送消息,或简单地调用runOnUIThread()

于 2012-12-02T23:05:03.447 回答