现在我们知道了怎样使用native code访问简单的数据类型和引用参考类型(string,array),下面我们来介绍怎样让jni代码去访问java中的成员变量和成员函数,然后可以再jni中回调java中的方法。

-------------------------------------------------------------------------------------

Accessing fields

java提供2中成员,静态成员和非静态成员,JNI支持了怎么样去get和set这些静态以及非静态成员的方法,下面来举一个例子。

先来访问非静态成员。

我们先在类中声明一个非静态的成员变量:


1. public class MyJNI extends Activity {  
2. /** Called when the activity is first created. */  
3. //declear a instance field  
4. private String s="123";


在点击按钮的时候我们把title的textview的字符串改成s,



1. MyJNI mj = new MyJNI();  
2.   
3. mj.accessField();  
4. tv.setText(mj.s);


java代码很简单,只要实现我们的功能就好了,下面来看jni是如何进入class中的成员变量的:



1. Java_com_android_jni_MyJNI_accessField(JNIEnv *env,jobject obj)  
2. {  
3.     jfieldID fid;  
4.     jstring jstr;  
5. const char *str;  
6.   
7. //get a reference to obj's class  
8.     jclass cls = (*env)->GetObjectClass(env,obj);  
9. //  jclass cls = (*env)->FindClass(env,"com/android/jni/Native");  
10. "-JNI-","here in native C!");  
11. //look for the instance field in cls  
12. "s",  
13. "Ljava/lang/String;");  
14. if(fid == NULL){  
15. "-JNI-","can not find field");  
16. return;  
17.     }  
18. //read the instance field s  
19.     jstr = (*env)->GetObjectField(env,obj,fid);  
20.     str = (*env)->GetStringUTFChars(env,jstr,NULL);  
21. if(str == NULL)  
22. return;  
23.     (*env)->ReleaseStringUTFChars(env,jstr,str);  
24. //create a new string and overwrite the instance field  
25. "abc");  
26. if(jstr == NULL)  
27. return; //out of memory  
28.     (*env)->SetObjectField(env,obj,fid,jstr);  
29. }



为了访问目标类中的成员变量,要做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”


android jni ——Field & Method --> Accessing Field_静态成员


ok,这部分结束,下面来看如何访问静态成员变量。

同样的java代码中:




1. public class MyJNI extends Activity {  
2. /** Called when the activity is first created. */  
3. //declear a instance field  
4. private static int si=100;  
5. private String s="123";


我们定义一个静态的整形变量si初始化为100,当我们点击按钮的时候通过jni访问static field来改变si的值,然后再title的textView中显示出来。


1. MyJNI mj = new MyJNI();  
2.   
3. mj.accessStaticField();  
4. tv.setText(mj.si+"");


我们来看下如何进入static field:



1. void  
2. Java_com_android_jni_MyJNI_accessStaticField(JNIEnv *env,jobject obj)  
3. {  
4. //store the field id  
5.     jint si;  
6.   
7. //get a reference to obj's class  
8.     jclass cls = (*env)->GetObjectClass(env,obj);  
9. "-JNI-","here in native C!");  
10.       
11. //look for the static field si in lcs  
12. "si","I");  
13. if(fid == NULL)  
14. return; //field not found  
15. //access the static field si  
16.     si = (*env)->GetStaticIntField(env,cls,fid);  
17.     (*env)->SetStaticIntField(env,cls,fid,200);  
18. }



大家可以看到只是调用的方法不一样,多了一个static,和非静态的使用方法一样。

-------------------------------------------------------------------------------------------------------

jni中访问class 中的field就到此结束,下面一篇会介绍如何访问java中class 的method。