jni,如何在本机代码中访问正确的对象示例

hjqgdpho  于 2021-07-07  发布在  Java
关注(0)|答案(2)|浏览(361)

我尝试在java中创建两个对象,用本机代码创建对象并访问它们的值。
java代码:
myobject.java文件

package com.myobject;

public class MyObject {

    public native void setId(int id); 
    public native int getId(); 

    public MyObject() {
        System.load("C:\\...MyObjects.dll");
    }
}

测试对象.java

package com.myobject;

import com.myobject.MyObject;

public class TestObjects {

    public static void main(String[] args) {

        MyObject obj1 = new MyObject();

        obj1.setId(1);

        System.out.println("obj1 id="+obj1.getId());

        MyObject obj2 = new MyObject();

        obj2.setId(2);

        System.out.println("obj1 id="+obj1.getId());
        System.out.println("obj2 id="+obj2.getId());

    }    
}

c++代码:
com\u myobject\u myobject.h


# include <jni.h>

# ifndef _Included_com_myobject_MyObject

# define _Included_com_myobject_MyObject

# ifdef __cplusplus

extern "C" {

# endif

/*
 * Class:     com_myobject_MyObject
 * Method:    setId
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_myobject_MyObject_setId
  (JNIEnv *, jobject, jint);

/*
 * Class:     com_myobject_MyObject
 * Method:    getId
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_myobject_MyObject_getId
  (JNIEnv *, jobject);

# ifdef __cplusplus

}

# endif

# endif

源.cpp


# include "com_myobject_MyObject.h"

# include "MyClass.h"

MyObject* myObject = NULL;

JNIEXPORT void JNICALL Java_com_myobject_MyObject_setId
(JNIEnv*, jobject, jint id) {

    myObject = new MyObject();

    myObject->setId(id);
}

JNIEXPORT jint JNICALL Java_com_myobject_MyObject_getId
(JNIEnv*, jobject) {

    if (myObject != NULL)
        return myObject->getId();
    else
        return -1;
}

我的班级.cpp


# include "MyClass.h"

MyObject::MyObject() {
    id = 0;
}

int MyObject::getId() {
    return id;
}

void MyObject::setId(int newId) {
    id = newId;
}

我的班级.h


# pragma once

class MyObject
{
private:

    int id;

public:

    MyObject();

    int getId();
    void setId(int);

};

但结果是两个java对象都返回来自同一对象的值:

obj1 id=1
obj1 id=2
obj2 id=2

如何在c++代码中创建与每个java对象相对应的对象的唯一示例,结果应该是:

obj1 id=1
obj1 id=1
obj2 id=2
a0x5cqrl

a0x5cqrl1#

我发现其中一个解决方案是在java对象中使用指向c++对象的指针:
java代码:
myobject.java文件

package com.myobject;

public class MyObject {

    public native long init();
    public native void setId(int id, long ptr); 
    public native int getId(long ptr); 

    public MyObject() {
        System.load("C:\\...MyObjects.dll");
    }
}

测试对象.java

package com.myobject;

import com.myobject.MyObject;

public class TestObjects {

    public static void main(String[] args) {

        MyObject obj1 = new MyObject();

        long lObj1 = obj1.init();

        obj1.setId(1, lObj1);

        System.out.println("obj1 id="+obj1.getId(lObj1));

        MyObject obj2 = new MyObject();

        long lObj2 = obj2.init();

        obj2.setId(2, lObj2);

        System.out.println("obj1 id="+obj1.getId(lObj1));
        System.out.println("obj2 id="+obj2.getId(lObj2));

    }    
}

c++代码:
com\u myobject\u myobject.h


# include <jni.h>

# ifndef _Included_com_myobject_MyObject

# define _Included_com_myobject_MyObject

# ifdef __cplusplus

extern "C" {

# endif

    /*
     * Class:     com_myobject_MyObject
     * Method:    init
     * Signature: ()J
     */
    JNIEXPORT jlong JNICALL Java_com_myobject_MyObject_init
    (JNIEnv*, jobject);

    /*
     * Class:     com_myobject_MyObject
     * Method:    setId
     * Signature: (IJ)V
     */
    JNIEXPORT void JNICALL Java_com_myobject_MyObject_setId
    (JNIEnv*, jobject, jint, jlong);

    /*
     * Class:     com_myobject_MyObject
     * Method:    getId
     * Signature: (J)I
     */
    JNIEXPORT jint JNICALL Java_com_myobject_MyObject_getId
    (JNIEnv*, jobject, jlong);

# ifdef __cplusplus

}

# endif

# endif

源.cpp


# include "com_myobject_MyObject.h"

# include "MyClass.h"

MyObject* myObject = NULL;

JNIEXPORT jlong JNICALL Java_com_myobject_MyObject_init
(JNIEnv*, jobject) {
    myObject = new MyObject();
    return (long)myObject;
}

/*
 * Class:     com_myobject_MyObject
 * Method:    setId
 * Signature: (IJ)V
 */
JNIEXPORT void JNICALL Java_com_myobject_MyObject_setId
(JNIEnv*, jobject, jint id, jlong ptr) {

    MyObject* pObject = (MyObject*)ptr;

    pObject->setId(id);
}

/*
 * Class:     com_myobject_MyObject
 * Method:    getId
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_myobject_MyObject_getId
(JNIEnv*, jobject, jlong ptr) {

    MyObject* pObject = (MyObject*)ptr;

    if (pObject != NULL)
        return pObject->getId();
    else
        return -1;

}

结果是:

obj1 id=1
obj1 id=1
obj2 id=2
fquxozlt

fquxozlt2#

在source.cpp中:
调用setid时,示例化myobject,将其存储在全局变量中,然后设置id。
调用getid时,您将获得最新示例化的myobject的id
所以我猜你的错误是使用了一个全局变量,它只能存储一个示例,最新的。

相关问题