ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
现在我们知道了怎样使用native code访问简单的数据类型和引用参考类型(string,array),下面我们来介绍怎样让jni代码去访问java中的成员变量和成员函数,然后可以再jni中回调java中的方法。 ------------------------------------------------------------------------------------- Accessing fields java提供2中成员,静态成员和非静态成员,JNI支持了怎么样去get和set这些静态以及非静态成员的方法,下面来举一个例子。 先来访问非静态成员。 我们先在类中声明一个非静态的成员变量: ~~~ public class MyJNI extends Activity { /**Called when the activity is first created. */ //declear a instance field private String s="123"; ~~~ 在点击按钮的时候我们把title的textview的字符串改成s, ~~~ MyJNI mj = new MyJNI(); mj.accessField(); tv.setText(mj.s); ~~~ java代码很简单,只要实现我们的功能就好了,下面来看jni是如何进入class中的成员变量的: ~~~ Java_com_android_jni_MyJNI_accessField(JNIEnv *env,jobject obj) { jfieldID fid; jstring jstr; const char *str; //get a reference to obj's class jclass cls = (*env)->GetObjectClass(env,obj); // jclass cls = (*env)->FindClass(env,"com/android/jni/Native"); __android_log_print(ANDROID_LOG_INFO,"-JNI-","here in native C!"); //look for the instance field in cls fid = (*env)->GetFieldID(env,cls,"s", "Ljava/lang/String;"); if(fid == NULL){ __android_log_print(ANDROID_LOG_INFO,"-JNI-","can not find field"); return; } //read the instance field s jstr = (*env)->GetObjectField(env,obj,fid); str = (*env)->GetStringUTFChars(env,jstr,NULL); if(str == NULL) return; (*env)->ReleaseStringUTFChars(env,jstr,str); //create a new string and overwrite the instance field jstr = (*env)->NewStringUTF(env,"abc"); if(jstr == NULL) return; //out of memory (*env)->SetObjectField(env,obj,fid,jstr); } ~~~ 为了访问目标类中的成员变量,要做2步,首先呼叫GetFieldID从类中来得到一个field ID,根据成员的名字和描述: fid = (*env)->GetFieldID(env,cls,"s", "Ljava/lang/String;"); 然后根据这个field ID来访问这个成员: jstr = (*env)->GetObjectField(env,obj,fid); 因为在java中string是对象,所以这边呼叫的是GetObjectField函数。 最后运行模拟器,点击按钮的时候textView会变成JNI中修改的“abc” ![](https://box.kancloud.cn/2016-08-03_57a197f8417ab.gif) ok,这部分结束,下面来看如何访问静态成员变量。 同样的java代码中: ~~~ public class MyJNI extends Activity { /**Called when the activity is first created. */ //declear a instance field private static int si=100; private String s="123"; ~~~ 我们定义一个静态的整形变量si初始化为100,当我们点击按钮的时候通过jni访问static field来改变si的值,然后再title的textView中显示出来。 ~~~ MyJNI mj = new MyJNI(); mj.accessStaticField(); tv.setText(mj.si+""); ~~~ 我们来看下如何进入static field: ~~~ void Java_com_android_jni_MyJNI_accessStaticField(JNIEnv *env,jobject obj) { jfieldID fid; //store the field id jint si; //get a reference to obj's class jclass cls = (*env)->GetObjectClass(env,obj); __android_log_print(ANDROID_LOG_INFO,"-JNI-","here in native C!"); //look for the static field si in lcs fid = (*env)->GetStaticFieldID(env,cls,"si","I"); if(fid == NULL) return; //field not found //access the static field si si = (*env)->GetStaticIntField(env,cls,fid); (*env)->SetStaticIntField(env,cls,fid,200); } ~~~ 大家可以看到只是调用的方法不一样,多了一个static,和非静态的使用方法一样。 ------------------------------------------------------------------------------------------------------- jni中访问class 中的field就到此结束,下面一篇会介绍如何访问java中class 的method。