0

私はjniを学ぼうとしています.Javaオブジェクトがjni c ++レイヤーでそれに関連付けられた値を持つことができるようにする方法を考えていました。現在、私はこのJavaコードを持っています。

public class Test 
{
    static
    {
        Runtime.getRuntime().loadLibrary("JNITests");
    }

    public native void setValue(int value);
    public native int getValue();

    public static void main(String[] args) 
    {
        Test test1 = new Test();
        test1.setValue(34);
        Test test2 = new Test();
        test2.setValue(23);
        System.out.println(test1.getValue());
    }
}

したがって、私がやろうとしているのは、各 Test オブジェクトが setValue を使用して jni に値を格納し、この c++ コードを使用して getValue を取得できるようにすることです。

#include <jni.h>
#include "Test.h"
int value;

JNIEXPORT void JNICALL Java_Test_setValue(JNIEnv *, jobject, jint newValue)
{
value = newValue;
}

JNIEXPORT jint JNICALL Java_Test_getValue(JNIEnv *, jobject)
{
return value;
}

ただし、問題は、test2 で setValue を使用してから test1 の値を出力すると、test2 に設定した値に変更されることです。これを修正するにはどうすればよいですか。各 jobject を int 値にマッピングしようとしましたが、それもうまくいきませんでした。

4

1 に答える 1

2

考えられる解決策は、ネイティブ コードで動的に割り当てられた構造体を使用することです。これを機能させるには、構造体を保持するメモリを (コンストラクターなどで) 割り当てる必要があります。その構造体のアドレスが Java 部分に戻され、Java オブジェクトに格納されます。次に、 と に対してgetValuesetValue割り当てられた構造体のメモリ アドレスを保持するパラメータが追加され、値の格納に使用できます。オブジェクトを破棄するときは、メモリを手動で解放する必要があります。


コードを使用すると、ネイティブ部分は次のようになります。

#include <cstdlib>
#include <jni.h>
#include "Test.h"

struct data {
    int value;
};

JNIEXPORT void JNICALL Java_Test_setValue0(JNIEnv *, jobject, jlong address, jint newValue)
{
    struct data *ptr = (struct data *)address;
    ptr->value = newValue;
}

JNIEXPORT jint JNICALL Java_Test_getValue0(JNIEnv *, jobject, jlong address)
{
    struct data *ptr = (struct data *)address;
    return ptr->value;
}

JNIEXPORT jlong JNICALL Java_Test_construct0(JNIEnv *, jobject) {
    struct data *ptr = (struct data *)malloc(sizeof(*ptr));
    return (jlong)ptr;
}

JNIEXPORT void JNICALL Java_Test_destruct0(JNIEnv *, jobject, jlong address) {
    struct data *ptr = (struct data *)address;
    free(ptr);
}

Java 部分は次のようになります。

public class Test 
{
    static
    {
        Runtime.getRuntime().loadLibrary("JNITests");
    }

    private long address;

    private native long construct0();
    private native void destruct0(long address);
    private native void setValue0(long address, int value);
    private native int getValue0(long address);

    public Test() {
        this.address = this.construct0();
    }

    @Override
    public void finalize() {
        this.destruct0(this.address);
        super.finalize();
    }

    public void setValue(int value) {
        this.setValue0(this.address, value);
    }

    public int getValue() {
        return this.getValue0(this.address);
    }

    public static void main(String[] args) 
    {
        Test test1 = new Test();
        test1.setValue(34);
        Test test2 = new Test();
        test2.setValue(23);
        System.out.println(test1.getValue());
    }
}

addressAPI を変更せずにパラメーターを導入するために、ネイティブ メソッドの名前を変更しました。

于 2013-10-06T14:22:05.730 に答える