5

私はJNIに比較的慣れていないので、JNIを使​​用してJavaオブジェクトの整数と配列をいじる基本を学びました。今、私はJavaオブジェクト内のJavaオブジェクトを変更/アクセスしようとしています。

私はインターネットとStackOverflowで検索してきましたが、これを行う方法をまだ見つけていません。

これが例です。

Javaの場合:

public class ObjectOne
{
    private byte[] buff;
    ...
    ...
}

public class ObjectTwo
{
    private ObjectOne obj;
    ...
    ...
}

JNIで、ObjectOneからObjectTwoを介して「バフ」にアクセスするにはどうすればよいですか?私はこのようなことを試みました...

JNIEXPORT void JNICALL Java_accessBuffThroughObjectTwo(JNIEnv *env, jobject obj, jobject objectTwo)
{
    jclass clazz;
    jclass bufferClazz;
    jobject bufferJObject;

    clazz = (*env)->GetObjectClass(env, objectTwo);
    fid = (*env)->GetFieldID(env, clazz, "obj", "Ljava/lang/Object;");
    bufferJObject = (*env)->GetObjectField(env, javascsicommand, fid);
    bufferClazz = (*env)->GetObjectClass(env, bufferJObject);  <-- Fails here for Access Violation
    fid = (*env)->GetFieldID(env, bufferClazz, "buff", "[B");
}

私が間違っていることについて何か助けはありますか?

4

1 に答える 1

15

コードを試すとき、次のようなアサーションを簡単に追加できます。

JNIEXPORT void JNICALL Java_accessBuffThroughObjectTwo(JNIEnv *env, jobject obj,  jobject objectTwo) {
    jclass clazz;
    jclass bufferClazz;
    jobject bufferJObject;
    jfieldID fid;

    clazz = (*env)->GetObjectClass(env, objectTwo);
    assert(clazz != NULL);
    fid = (*env)->GetFieldID(env, clazz, "obj", "Ljava/lang/Object;");
    assert(fid != NULL);
    bufferJObject = (*env)->GetObjectField(env, javascsicommand, fid);
    assert(bufferJObject != NULL);
    bufferClazz = (*env)->GetObjectClass(env, bufferJObject);
    assert(bufferClazz != NULL);
    fid = (*env)->GetFieldID(env, bufferClazz, "buff", "[B");
    assert(fid != NULL);
}

fidそうすることで、最初のものが NULL になることが最初にわかります。これは、ObjectTwoクラスに type のフィールドがないためjava.lang.Objectです。この行を次のように変更する必要があります (ただし、の代わりに正しいパッケージを追加しますcom/package)。

fid = (*env)->GetFieldID(env, clazz, "obj", "Lcom/package/ObjectOne;");

再度実行すると、fid が null ではなくなり、アサーションがパスすることがわかります。

javascsicommand他の人が示唆しているように、私はそうあるべきだと信じていますobjectTwo

アサーションが失敗する次の場所は onbufferJObjectです。これは、フィールドは存在しますが、オブジェクトが NULL であるためです。Java コードを確認すると、objフィールドがインスタンス化されておらず、null.

Java コードを次のように変更します。

public class ObjectTwo
{
    private ObjectOne obj = new ObjectOne();
    ...
    ...
}

これで、アサーションを渡し、さらに他のすべてのアサーションを渡します。

要約すると、nullオブジェクトにアクセスしてリフレクションを呼び出そうとしていました。

bufferClazz = (*env)->GetObjectClass(env, bufferJObject); <-- The bufferJObject was NULL
于 2012-08-06T08:57:02.043 に答える