[JNI]开发之旅(6)JNI函数中访问java类中对象的属性

JNI函数的实现在c/c++中实现的,如果想访问java中定义的类对象的实例域需要三个步骤

1.通过GetObjectClass()函数获得该对象的类class,返回值是一个jclass;
2.调用GetFieldID函数得到需要访问的实例域(变量)在该c类中id
3.调用Get【Type】Field()得到访问的变量值。其中【Type】对应变量的类型。
例如:java中有一个int age 对应的【Type】就是Int

GetIntField()


实例1:访问java类中num属性,并对其做加法运算。

java 层:

public class JNIUtils {

    public int num = 10;

    public native int addNum();

    static {
        System.loadLibrary("native-lib");
    }
}

c++层:

#include <jni.h>
#include <string.h>
#include <stdio.h>

//访问java对象中num属性,并对其作加法运算
extern "C"
jint Java_com_honjane_ndkdemo_JNIUtils_addNum( JNIEnv* env, jobject jobj){
    //1.获得实例对应的class类
    jclass jcls = env->GetObjectClass(jobj);

    //2.通过class类找到对应的field id
    //num 为java类中变量名,I 为变量的类型int
    jfieldID fid = env->GetFieldID(jcls,"num","I");

    //3.通过实例object获得对应的field
    jint jnum = env->GetIntField(jobj,fid);
    //add
    jnum += 10;

    return jnum;
}

输出结果:

I/main----addNum: 20

实例2:访问java层static属性,并对其操作

java层:


    public static String name = "honjane";

    public native void accessStaticField();

定义一个static的变量,然后在c++获取这个变量,对其操作,通过getStaticField返回到java显示。

c++层:


//访问java中静态变量name,并对其赋值
extern "C"
void Java_com_honjane_ndkdemo_JNIUtils_accessStaticField( JNIEnv* env, jobject jobj){
    //1.获得实例对应的class类
    jclass jcls = env->GetObjectClass(jobj);

    //2.通过class类找到对应的静态field id
    //name 为java类中变量名,Ljava/lang/String; 为变量的类型String
    jfieldID fid = env->GetStaticFieldID(jcls,"name","Ljava/lang/String;");

    //3.通过class获得对应的静态field
    jstring jstr = (jstring)env->GetStaticObjectField(jcls,fid);
    // 将jstring类型转换成字符指针
    const char* cstr = env->GetStringUTFChars(jstr, JNI_FALSE);
    //定义字符数组
    char text[30] = "hello ";
    //拼接字符
    strcat(text, cstr);
    jstring new_str = env->NewStringUTF(text);

    // 将jstring类型的变量 , 设置到java 
    env->SetStaticObjectField(jcls, fid, new_str);
}

输出结果:

I/main----name: hello honjane

这里有几个地方需要注意:
static变量的Field是通过GetStatic【[Type】Field(jcls…),传入的是class,而非static变量获取是通过Get【Type】Field(jobj…)传入的参数是实例object;同理SetStatic【[Type】Field(jcls…)传入的是类class,Set【Type】Field(jobj…)传入的是实例object。

这个也很好理解,静态变量或者方法属于该对象的类class,而非静态变量或方法属于该对象的实例。所以要根据它属于的情况来传参数。

实例3:访问java对象的私有变量

java层


    private int age = 21;

    public native void accessPrivateField();

    public int getAge(){
        return age;
    }

c++层

//访问java中私有变量age
extern "C"
void Java_com_honjane_ndkdemo_JNIUtils_accessPrivateField( JNIEnv* env, jobject jobj){

    jclass jcls = env->GetObjectClass(jobj);

    jfieldID jfid = env->GetFieldID(jcls,"age","I");

    jint jage = env->GetIntField(jobj, jfid);

    jage++;

    env->SetIntField(jobj, jfid, jage);
}

输出结果:

I/main----age修改前: 21
I/main----age修改后: 22

我们看到实例3中private变量与实例1中public变量访问在c/c++没有什么区别,访问方式相同。

变量的访问先介绍到这里,下一节介绍jni访问java中方法

源码:https://github.com/honjane/JNIDemo

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值