簡體   English   中英

在Java中的JNI中使用非靜態對象

[英]Using non-static objects in jni in java

我正在嘗試學習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());
    }
}

所以我想做的就是使用此c ++代碼使每個Test對象使用setValue和getgetValue在jni中存儲一個值。

#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值,但這也不起作用。

可能的解決方案可能是在本機代碼中使用動態分配的結構。 為此,您必須分配(例如,在構造函數中)一些保存該結構的內存。 該結構的地址被傳遞回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());
    }
}

我重命名了本機方法,以在不更改API的情況下引入address參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM