接着上一篇的学习()
今天学习JNI中本地语言访问Java类中的属性与方法:
首先要访问Java类中的属性与方法,我们要先去了解一下属性与方法的签名:因为在使用本地方法访问的时候需要使用到这些签名;
以后要使用到各种签名可以上表查询,不过jdk中有个命令工具javap,可以轻松的为我们显示出java中的各种属性与方法的签名,
下面我们来看下使用的方法;
一般使用的时候,直接来个javap -s -p 完整类名,加上-p,可以属性所有的属性与方法的签名,下面看下我的例子中的生成:
看,用这个javap工具很容易生成,到时候我们在本地方法中需要的时候,直接把签名照着写进去进行,还能提供正确哈。
好了,了解了签名,下面可以进入正题了
(一):本地方法访问Java类中的属性
java例子代码如下:
package com.jiangqq.jni; /** * 本地方法访问Java类的属性与方法例子 * @author jiangqq * CSDN 记录自己的成长历程 */ public class TestJni { private int sum=10; double add(double a,double b) { return a+b; } public native void invoked(); public static void main(String[] args) { System.loadLibrary("nativeCode4"); TestJni testJni=new TestJni(); testJni.invoked(); } }
要从本地方法中去访问到Java类,我们可以再JNI.h文件发现三个主要获取jclass的方法,因为在jni中已经定义了jclass类型来标识Java的class类了
- jclass FindClass(const char *name) { return functions->FindClass(this, name); }
- jclass GetObjectClass(jobject obj) { return functions->GetObjectClass(this,obj); }
- jclass GetSuperclass(jclass sub) { return functions->GetSuperclass(this, sub); }
上面的三个方法,我们都可以再jni.h头文件中找到,现在开始使用本地方法访问java中的属性并且修改;
我的例子中
步骤:
- 获取jclass,(上面的例子的native方法时非静态的,所以传入到本地方法是实例对象,可以使用第二种获取jclass的方法)
- 获取jfieldID,(jfieldID GetFieldID(jclass clazz, const char *name, const char *sig) {return functions>GetFieldID(this,clazz,name,sig); })
- 设置该属性的新值 使用 Set<Type>Field,Type代码该属性的类型,
上面的那些方法(尤其第三个,我们都可以再jni.h头文件中找到相对应的),如果要访问静态的属性也是类似的,大家可以尝试一下的;
访问Java属性与修改属性的本地代码如下:
#include"com_jiangqq_jni_TestJni.h" #includeJNIEXPORT void JNICALL Java_com_jiangqq_jni_TestJni_invoked (JNIEnv * env, jobject obj) { //本地代码调用修改Java属性/// jclass j_class= env->GetObjectClass(obj); jfieldID j_sum= env->GetFieldID(j_class,"sum","I"); env->SetIntField(j_class,j_sum,20); jint j_sum2=env->GetIntField(j_class,j_sum); printf("%d\n",j_sum2); }
(二)本地方法访问Java的方法:
步骤:
- 和上面的相似,首先获取jclass,(参照本地语言访问java属性的第一步)
- 获取jmethodID, jmethodID (JNICALL *GetMethodID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
- 调用Call<Type>Method,介绍一个比较常用的方法:我们可以使用Call<Type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)
[注]如果要调用的方法时一个静态方法,那么就可以使用CallStatic<Type>Method(...),当然这些方法也可以在jni.h头文件中找到.
调用Java语言中的方法的本地代码如下:
#include"com_jiangqq_jni_TestJni.h" #includeJNIEXPORT void JNICALL Java_com_jiangqq_jni_TestJni_invoked (JNIEnv * env, jobject obj) { ///本地代码调用Java方法/ jclass j_class= env->GetObjectClass(obj); jmethodID j_add= env->GetMethodID(j_class,"add","(DD)D"); jdouble j_add_sum= env->CallDoubleMethod(obj,j_add,1.1,3.2); printf("%.2f\n",j_add_sum); }
例子代码下载链接: