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 クラスにコールバックしようとしています

ええ、それが問題です。クラスでmethodIDを検索しましたが、 !の元のjobjectインスタンスでそのmethodIDcom.main.myappを呼び出そうとしています。別の「名前空間」からメソッドを呼び出したい場合は、いくつかのオプションがあります。org.myorg.ImageRenderer

  1. クラスを見つけるだけで十分であり、オブジェクトを必要としないように、メソッドは静的でなければなりません
  2. 別のオブジェクトは、ネイティブ メソッドでパラメーターとして渡す必要があります。
  3. 別のオブジェクトは、元のオブジェクト (ネイティブ メソッドを宣言したオブジェクト) のメンバー/ゲッターとしてアクセス可能である必要があり、JNI メソッドのルックアップと呼び出しを介してアクセスできます。
于 2012-12-02T21:05:24.997 に答える
0

関数は Java から呼び出されるため、 を呼び出すべきではありませんAttachCurrentThread

関数は Java からオブジェクトへの参照を受け取ります。このorg.myorg.myRendererオブジェクトの renderImageFrame() はネイティブ メソッドです (すべてのネイティブ メソッドは Java 環境envを最初のパラメーターとして受け取り、そのオブジェクト参照thizを 2 番目のパラメーターとして受け取ることがよくあります。

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()。UI スレッドを必要とするメソッドを GL スレッドから呼び出すことはお勧めできません。を発行するpostか、メッセージを送信するか、単に を呼び出す必要がありますrunOnUIThread()

于 2012-12-02T23:05:03.447 に答える