接着上一篇的学习( JNI学习笔记(二)JNI中的java语言与本地C/C++语言之间的映射)

      今天学习JNI中本地语言访问Java类中的属性与方法:

      

      首先要访问Java类中的属性与方法,我们要先去了解一下属性与方法的签名:因为在使用本地方法访问的时候需要使用到这些签名;

       

   

       以后要使用到各种签名可以上表查询,不过jdk中有个命令工具javap,可以轻松的为我们显示出java中的各种属性与方法的签名,

  

       下面我们来看下使用的方法;

        

       

        一般使用的时候,直接来个javap -s -p 完整类名,加上-p,可以属性所有的属性与方法的签名,下面看下我的例子中的生成:

    

       

       看,用这个javap工具很容易生成,到时候我们在本地方法中需要的时候,直接把签名照着写进去进行,还能提供正确哈。

        好了,了解了签名,下面可以进入正题了   

 

 (一):本地方法访问Java类中的属性

    java例子代码如下:

package com.jiangqq.jni; /**  * 本地方法访问Java类的属性与方法例子  * @author jiangqq  * <a href http://blog.csdn.net/jiangqq781931404>CSDN 记录自己的成长历程</a>  */ 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中的属性并且修改;
我的例子中
       步骤:
  1. 获取jclass,(上面的例子的native方法时非静态的,所以传入到本地方法是实例对象,可以使用第二种获取jclass的方法)
  2. 获取jfieldID,(jfieldID GetFieldID(jclass clazz, const char *name, const char *sig) {return functions>GetFieldID(this,clazz,name,sig); })
  3. 设置该属性的新值 使用 Set<Type>Field,Type代码该属性的类型,
    上面的那些方法(尤其第三个,我们都可以再jni.h头文件中找到相对应的),如果要访问静态的属性也是类似的,大家可以尝试一下的;
     
      访问Java属性与修改属性的本地代码如下:    
#include"com_jiangqq_jni_TestJni.h" #include<stdio.h> JNIEXPORT 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的方法:
     步骤:
  1.     和上面的相似,首先获取jclass,(参照本地语言访问java属性的第一步)
  2.     获取jmethodID, jmethodID (JNICALL *GetMethodID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
  3.      调用Call<Type>Method,介绍一个比较常用的方法:我们可以使用Call<Type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)
    [注]如果要调用的方法时一个静态方法,那么就可以使用CallStatic<Type>Method(...),当然这些方法也可以在jni.h头文件中找到.
     
     调用Java语言中的方法的本地代码如下:
#include"com_jiangqq_jni_TestJni.h" #include<stdio.h> JNIEXPORT 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); }