7.1 java中的基本類型和引用類型的簽名規(guī)則
jni中 java類的簽名為: L + 包名 + 類名,再將原來的
.
改為/
分隔符即可性昭。
例如:java中的java.lang.String
的簽名為Ljava/lang/String;
拦止。java中的基本類型的簽名為:
Field Descriptor | Java Language Type |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
V | void |
Object | L用/分割的包名 |
- java 中的數(shù)組的簽名為:左中括號(hào)+對(duì)象或者基本類型的簽名即可糜颠;
Field Descriptor | Java Language Type |
---|---|
object[] | [Ljava/lang/Object; |
int[] | [I |
float[] | [F |
7.2 JNI中訪問訪問java對(duì)象的字段并修改
JNI中修改任何java對(duì)象的字段值一般分為如下三步:
- 先找到類
- 找到類的字段id
- 通過字段id獲取或者更新對(duì)象的該字段
如果類實(shí)例中還存在別的類的實(shí)例 也是按上面的邏輯分析一層層解剖就行
例如:
定義一個(gè)叫Person的java類和House的java類:
public class House {
public int size = 100;
public String location = "Beijing";
}
public class Person {
protected String name;
protected int age;
protected House house;
public static int num = 0;
public Person(String name)
{
this.name = name;
this.house = new House();
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public static int getNum() {
return num;
}
}
在默認(rèn)工程的MainActivity添加兩個(gè)JNI方法聲明第一個(gè)為成員訪問,第二個(gè)靜態(tài)方法其兴。他們?cè)贘NI層的生成的代碼是不一樣的。在成員實(shí)例方法jni方法中的前兩個(gè)參數(shù) : JNIEnv env, jobject thiz元旬。thiz代表著所在java類的實(shí)例搁拙。例如本例中是MainActivity
的java實(shí)例。取決于這個(gè)方法生命在哪個(gè)類中。
public native void accessField(Person person);
在static 的 jni方法中的前兩個(gè)參數(shù) : JNIEnv *env, jclass clazz酪碘。clazz代表著所在java類朋譬。例如本例中是MainActivity
的java類兴垦。取決于這個(gè)方法生命在哪個(gè)類中徙赢。
public static native void accessStaticField(Person person);
接下來在jni中訪問Person類的成員變量:
extern "C"
JNIEXPORT void JNICALL
Java_com_memetghini_javaobject_MainActivity_accessField(JNIEnv *env, jobject thiz, jobject person) {
//成員變量
//首先找到類探越,參數(shù)是jni對(duì)象
jclass cls = env->GetObjectClass(person);
//再找到成員變量字段id。第一個(gè)參數(shù)是上面找到的類钦幔,第二個(gè)參數(shù)是字段名枕屉,第三個(gè)參數(shù)為字段簽名
jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
//為該成員變量設(shè)值鲤氢,第一個(gè)參數(shù)為jni對(duì)象西潘,第二個(gè)參數(shù)為要設(shè)值的字段id,第三個(gè)參數(shù)為具體的值
jstring str = env->NewStringUTF("Kadi");
env->SetObjectField(person, fid, str);
//成員對(duì)象
//上面已經(jīng)找到了類哨颂,所以先直接找到字段id
jfieldID house_fid = env->GetFieldID(cls, "house", "Lcom/memetghini/javaobject/House;");
//再找jni對(duì)象,再?gòu)膶?duì)象中獲取字段值或者更改內(nèi)容威恼,接下來的跟上面相似
jobject house_obj = env->GetObjectField(person, house_fid);
jclass house_cls = env->GetObjectClass(house_obj);
jfieldID size_fid = env->GetFieldID(house_cls, "size", "I");
env->SetIntField(house_obj, size_fid, 1000000);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_memetghini_javaobject_MainActivity_accessStaticField(JNIEnv *env, jclass clazz, jobject person) {
//靜態(tài)變量的讀取也是一樣的先通過GetStaticFieldID獲取靜態(tài)變量的字段id
jfieldID num_fid = env->GetStaticFieldID(clazz, "num", "I");
//在用靜態(tài)變量的字段id獲取具體的值品姓。第一個(gè)變量為類類型箫措,第二個(gè)為靜態(tài)變量字段id
int num = env->GetStaticIntField(clazz, num_fid);
LOGI("jni num main = %d", num);
//更改靜態(tài)變量的值。第一個(gè)參數(shù)為類類型蒂破,第二個(gè)為靜態(tài)變量字段id馏谨,第三個(gè)為具體的值
env->SetStaticIntField(clazz, num_fid, 777);
}