JNI基础(7): JNI访问和修改Java类

2022-01-12  本文已影响0人  MemetGhini
7.1 java中的基本类型和引用类型的签名规则
Field Descriptor Java Language Type
Z boolean
B byte
C char
S short
I int
J long
F float
D double
V void
Object L用/分割的包名
Field Descriptor Java Language Type
object[] [Ljava/lang/Object;
int[] [I
float[] [F
7.2 JNI中访问访问java对象的字段并修改

JNI中修改任何java对象的字段值一般分为如下三步:

如果类实例中还存在别的类的实例 也是按上面的逻辑分析一层层解剖就行

例如:
定义一个叫Person的java类和House的java类:

public class House {
    public int size = 100;
    public String location = "Beijing";
}

public class Person {

    protected String name;
    protected int age;
    protected House house;
    public static int num = 0;

    public Person(String name)
    {
        this.name = name;
        this.house = new House();
    }
    public String getName() {
        return name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public static int getNum() {
        return num;
    }
}

在默认工程的MainActivity添加两个JNI方法声明第一个为成员访问,第二个静态方法。他们在JNI层的生成的代码是不一样的。在成员实例方法jni方法中的前两个参数 : JNIEnv env, jobject thiz。thiz代表着所在java类的实例。例如本例中是MainActivity的java实例。取决于这个方法生命在哪个类中。

public native void accessField(Person person);

在static 的 jni方法中的前两个参数 : JNIEnv *env, jclass clazz。clazz代表着所在java类。例如本例中是MainActivity的java类。取决于这个方法生命在哪个类中。

public static native void accessStaticField(Person person);

接下来在jni中访问Person类的成员变量:

extern "C"
JNIEXPORT void JNICALL
Java_com_memetghini_javaobject_MainActivity_accessField(JNIEnv *env, jobject thiz, jobject person) {
    //成员变量
    //首先找到类,参数是jni对象
    jclass cls = env->GetObjectClass(person);
    //再找到成员变量字段id。第一个参数是上面找到的类,第二个参数是字段名,第三个参数为字段签名
    jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
    //为该成员变量设值,第一个参数为jni对象,第二个参数为要设值的字段id,第三个参数为具体的值
    jstring str = env->NewStringUTF("Kadi");
    env->SetObjectField(person, fid, str);

    //成员对象
    //上面已经找到了类,所以先直接找到字段id
    jfieldID house_fid = env->GetFieldID(cls, "house", "Lcom/memetghini/javaobject/House;");
    //再找jni对象,再从对象中获取字段值或者更改内容,接下来的跟上面相似
    jobject house_obj = env->GetObjectField(person, house_fid);
    jclass house_cls = env->GetObjectClass(house_obj);
    jfieldID size_fid = env->GetFieldID(house_cls, "size", "I");
    env->SetIntField(house_obj, size_fid, 1000000);
}


extern "C"
JNIEXPORT void JNICALL
Java_com_memetghini_javaobject_MainActivity_accessStaticField(JNIEnv *env, jclass clazz, jobject person) {
    //静态变量的读取也是一样的先通过GetStaticFieldID获取静态变量的字段id
    jfieldID num_fid = env->GetStaticFieldID(clazz, "num", "I");
    //在用静态变量的字段id获取具体的值。第一个变量为类类型,第二个为静态变量字段id
    int num = env->GetStaticIntField(clazz, num_fid);
    LOGI("jni num main = %d", num);
    //更改静态变量的值。第一个参数为类类型,第二个为静态变量字段id,第三个为具体的值
    env->SetStaticIntField(clazz, num_fid, 777);
}

上一篇下一篇

猜你喜欢

热点阅读