Java: JNI返回Java对象(转)

例:

从Native层返回一个Java对象,有两种操作

1. 传入一个创建好的Java对象,只在JNI代码中做赋值操作并返回;
2. 完全在JNI代码中新建一个对象,赋值并返回;

创建一个Person类

public class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

Native方法

//方法1 从Java层传入一个对象
public native Person getPerson(Person person);
//方法2 完全从Native代码中创建对象
public native Person getPerson2();

C++代码

方法1:

extern "C"
JNIEXPORT jobject JNICALL
Java_com_myapplication_MainActivity_getPerson(JNIEnv *env, jobject instance,
                                                      jobject person) {
    
    // 找到对象的Java类
    jclass myClass = env->FindClass("com/myapplication/Person");

    // 对应的Java属性
    jfieldID name = env->GetFieldID(myClass, "name", "Ljava/lang/String;");
    jfieldID age = env->GetFieldID(myClass, "age", "I");

    //属性赋值,person为传入的Java对象
    env->SetObjectField(person, name, env->NewStringUTF("liuwei"));
    env->SetIntField(person, age, 20);

    return person;
}

方法2:

extern "C"
JNIEXPORT jobject JNICALL
Java_com_myapplication_MainActivity_getPerson2(JNIEnv *env, jobject instance) {
   
    jclass myClass = env->FindClass("com/myapplication/Person");
    // 获取类的构造函数,记住这里是调用无参的构造函数
    jmethodID id = env->GetMethodID(myClass, "<init>", "()V");
    // 创建一个新的对象
    jobject person_ = env->NewObject(myClass, id);
    
    jfieldID name = env->GetFieldID(myClass, "name", "Ljava/lang/String;");
    jfieldID age = env->GetFieldID(myClass, "age", "I");

    env->SetObjectField(person_, name, env->NewStringUTF("liuwei"));
    env->SetIntField(person_, age, 20);

    return person_;
}

可以看到,方法1和方法2的代码区别就2行:

     // 获取类的构造函数,记住这里是调用无参的构造函数
    jmethodID id = env->GetMethodID(myClass, "<init>", "()V");
    // 创建一个新的对象
    jobject person_ = env->NewObject(myClass, id);

在开发时  env->GetMethodID(myClass, "<init>", "()V"); 很可能会在写代码是标红,提示无法找到 <init>, 不需要理会,直接编译就好了。

调用:

TextView tv = findViewById(R.id.sample_text);

Person person = new Person();
//传入Java对象,返回的也是同一个对象
getPerson(person);

tv.setText(person.getName() // 方法1
           + " : " +
           getPerson2().getAge() // 方法2
    );

本文转自:

1. Android JNI开发--JNI返回Java对象

 

posted @ 2020-11-23 10:31  夜行过客  阅读(3783)  评论(0编辑  收藏  举报