c中调用java_JNI开发系列③C语言调用Java字段与方法

前情提要

在前面 , 我们已经熟悉了JNI的开发流程 , .h头文件的分析 , 生成头文件javah命令 , 以及java类型在C语言中的表现形式 , 值得注意的是 , java中的所有引用类型都是jobject类型 , native生成的函数 , 以Java_全类名_方法名表示,包名的.以_表示 。

概述

在开篇的时候 ,我们就使用java的native方法调用过C函数 , 返回了一个String类型的字符串 , 使用(*Env)->NewStringUTF(Env, "Jni C String");函数 , 我们将字符指针转换成jstring , java类型的字符串返回给了我们的java层 。今天我们来学习 , 使用C语言来调用Java的字段与方法 。

part 1 : C 函数访问java字段

一 , 定义Java 的String类型字段与修改字段的native方法

// 使用C语言修改java字段

public String name = "zeno" ;

// C语言修改java String 类型字段本地方法

public native void accessJavaStringField() ;

// 调用

HelloJni jni = new HelloJni() ;

System.out.println("修改前 name 的值:"+jni.name);

//C语言修改java字段本地方法

jni.accessJavaStringField();

System.out.println("修改后 name 的值:"+jni.name);

二 , 在C语言头文件中定义native方法的实现函数 , 并实现

// com.zeno.jni_HelloJNI.h

JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField

(JNIEnv *, jobject);

// Hello_JNI.c

/*C语言访问java String类型字段*/

JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField

(JNIEnv *env, jobject jobj) {

// 得到jclass

jclass jcls = (*env)->GetObjectClass(env, jobj);

// 得到字段ID

jfieldID jfID = (*env)->GetFieldID(env, jcls, "name", "Ljava/lang/String;");

// 得到字段的值

jstring jstr = (*env)->GetObjectField(env, jobj, jfID);

// 将jstring类型转换成字符指针

char* cstr = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);

//printf("is vaule:%s\n", cstr);

// 拼接字符

char text[30] = " xiaojiu and ";

strcat(text, cstr);

//printf("modify value %s\n", text);

// 将字符指针转换成jstring类型

jstring new_str = (*env)->NewStringUTF(env, text);

// 将jstring类型的变量 , 设置到java 字段中

(*env)->SetObjectField(env, jobj, jfID, new_str);

}

三 , 输出

修改前 name 的值:zeno

修改后 name 的值: xiaojiu and zeno

四 , 分析

首先来分析C函数:

JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField

(JNIEnv *env, jobject jobj)

JNIEXPORT jstring JNICALL Java_com_zeno_jni_HelloJni_getStringFromC

(JNIEnv *Env, jclass jclazz)

我们可以看出两处不同 , 一处是返回值类型 , 一处是函数参数类型 ,返回值类型没什么可讲的 , 在分析.h头文件的时候 , 已经详细讲述了 。那 , 这两个函数参数类型jobject与jclass有什么区别呢 ? 这两个类型表示 , Java的native函数 , 是成员方法还是类方法 , 成员方法需要对象.方法名 , 类方法则类名.方法名 , 可以在main方法里面直接使用 。

接下来是:

// 得到jclass jclass就好比java的.class对象

jclass jcls = (*env)->GetObjectClass(env, jobj);

为什么要得到jclass呢 ?

因为 ,我们要获取字段ID , 在JNI中 , 获取java字段与方法都需要签名。而签名是在类加载的时候完成 , 所以在获取字段ID的时候需要传入jclass 。

// 得到字段ID

jfieldID jfID = (*env)->GetFieldID(env, jcls, "name", "Ljava/lang/String;");<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值