【Android NDK 开发】JNI 方法解析 ( C/C++ 设置 Java 对象字段 | 查找字段 | 设置字段 )

举报
韩曙亮 发表于 2022/01/11 00:22:29 2022/01/11
【摘要】 文章目录 I . 设置 Java 对象 属性 流程II . 查找 Java 对象属性 ( GetFieldID )III . 设置 Java 对象属性 ( SetXxxField ) ...



I . 设置 Java 对象 属性 流程



设置 Java 对象字段流程 :


① 获取属性 ID :

调用 jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) 方法 , 获取对象属性 ID ;

② 根据属性 ID 设置对象属性 :

调用 void SetIntField(jobject obj, jfieldID fieldID, jint value) 方法 , 设置对象属性 ;



II . 查找 Java 对象属性 ( GetFieldID )



1 . 函数原型 : 通过 jclass 对象 , 属性名称名称 , 和 类型签名 , 获取 Java 类对象对应的 属性 ID ;

返回值 : Java 类对象 对应的 属性 ID ( jfieldID 类型变量 )

参数 :

  • jclass clazz : 要获取的 Java 对象方法对应的 Java 类对象 ;
  • const char* name : 属性名称 ;
  • const char* sig : 类型签名 ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetFieldID 方法
    jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
    { return functions->GetFieldID(this, clazz, name, sig); }
    ...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2 . 代码示例 : 获取 Student 类的 getAge 方法 ;

student_class 是 Student 类对应的 C/C++ 中的 jclass 类型变量 ;
“age” 是 属性名称 ;
“I” 是 属性类型签名 ;

extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
	//1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);

    //2 . 获取 Student 的 private int age 属性
    jfieldID age_field_id = env->GetFieldID(student_class, "age", "I");
	...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

涉及到的类型签名可以参考 : https://hanshuliang.blog.csdn.net/article/details/104108556#V__javap_____141



III . 设置 Java 对象属性 ( SetXxxField )



1 . 函数原型 : 通过 Java 对象 , 属性 ID , 和 Java 数据类型属性参数 , 设置对应的 Java 对象属性 ;

返回值 : void

参数 :

  • jobject obj : 要设置属性的 Java 对象 ;
  • jfieldID fieldID : 属性 ID ;
  • jint value : Java 的 int 类型属性值 ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 SetIntField 方法
    void SetIntField(jobject obj, jfieldID fieldID, jint value)
    { functions->SetIntField(this, obj, fieldID, value); }
    ...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2 . 设置方法汇总 :


设置 int 类型属性 , 调用 void SetIntField(jobject obj, jfieldID fieldID, jint value) 方法 ;
设置 boolean 类型属性 , 调用 void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value) 方法 ;

下面是设置 8 种基本数据类型 和 引用类型 , 共 9 中类型应该调用的方法 ;


注意 : 所有设置的类型 , 都是 Java 数据类型 , 如 jobject , jint , jboolean 类型 ;


struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 SetXxxField 方法
    void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
    { functions->SetObjectField(this, obj, fieldID, value); }
    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value)
    { functions->SetBooleanField(this, obj, fieldID, value); }
    void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
    { functions->SetByteField(this, obj, fieldID, value); }
    void SetCharField(jobject obj, jfieldID fieldID, jchar value)
    { functions->SetCharField(this, obj, fieldID, value); }
    void SetShortField(jobject obj, jfieldID fieldID, jshort value)
    { functions->SetShortField(this, obj, fieldID, value); }
    void SetIntField(jobject obj, jfieldID fieldID, jint value)
    { functions->SetIntField(this, obj, fieldID, value); }
    void SetLongField(jobject obj, jfieldID fieldID, jlong value)
    { functions->SetLongField(this, obj, fieldID, value); }
    void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
    { functions->SetFloatField(this, obj, fieldID, value); }
    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)
    { functions->SetDoubleField(this, obj, fieldID, value); }

	//设置静态属性
    jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
    { return functions->GetStaticMethodID(this, clazz, name, sig); }
    ...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

3 . 代码示例 : 获取 Student 类的 getAge 方法 ;

student 是 Student 类对应的 C/C++ 中的 Java 对象 ;
age_field_id 是 属性 ID ;
90 是 属性值 , jint 类型 ;

extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
	//1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);

    //2 . 获取 Student 的 private int age 属性
    jfieldID age_field_id = env->GetFieldID(student_class, "age", "I");

	//3 . 设置 Student 的 age 属性值 90
	env->SetIntField(student, age_field_id, 90);
	...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/104179752

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。