之前已经知道了如何在java层调用native层的代码。现在就来了解一下native层如何调用java层
JNIEnv
JNIEnv类型代表了java环境,通过JNIEnv*指针就可以对Java端代码进行操作。
JNIEnv类中的一些函数如下:
- NewObject:创建Java类中的对象
- NewString:创建Java类中的String对象
- New<Type>Array:创建类型为Type的数组对象
- Get<Type>Field:获取类型为Type的字段
- Set<Type>Field:设置类型为Type的字段
- GetStatic<Type>Field:获取类型为Type的static字段
- SetStatic<Type>Field:设置类型为Type的static字段
- GetFieldID:获取java属性 对应jfieldID
- GetMehtodID:获取java函数ID 对应jmethodID
- Call<Type>Method:调用返回类型为Type的方法
- CallStatic<Type>Method:调用返回类型为Type的static方法
jobject参数obj
如果native方法不是static,obj代表native方法的类实例
如果native方法是static,obj就代表nativve方法的类的class对象实例
GetFieldID(jclass clazz,const char* name,const char* sign)
clazz:依赖类对象的class对象
name:这个字段的名称
sign:这个字段的签名
查看类的签名用javap -s -p HelloTest.java
实例讲解
需要被调用的java代码
public class HelloTest {
public int c;
public int add(int a,int b){
return a+b;
}
public void setC(int c) {
this.c = c;
}
}
native调用java层代码
- 获取类实例
- 获得构造函数
- 创建对象
- 获得方法ID
- 调用方法
JNIEXPORT void JNICALL Java_com_example_jnitest_JniUtils_CcallJava(JNIEnv *env, jobject obj){
jclass hellotest_clazz = env->FindClass("com/example/jnitest/HelloTest");//获取类hellotest类
jmethodID construction_id = env->GetMethodID(hellotest_clazz,"<init>", "()V");//获取构造函数
jobject hellotest_obj = env->NewObject(hellotest_clazz,construction_id);//创建对象
jmethodID methodId_add = env->GetMethodID(hellotest_clazz,"add","(II)I");//获取add method
jint result = env->CallIntMethod(hellotest_obj,methodId_add,1,2);//调用add
LOGI("1 add 2 = %d.\n",result);
jmethodID methodId_setC = env->GetMethodID(hellotest_clazz,"setC","(I)V");
env->CallVoidMethod(hellotest_obj,methodId_setC,1L);
jfieldID fieldId_prop = env->GetFieldID(hellotest_obj,"c","I");
jint prop = env->GetIntField(hellotest_clazz,fieldId_prop);
LOGI("TAGCcallJava: hellotest's C is %d\n",prop);
}
获得jclass的三个方法
- FindClass(const char* clsName):通过类的名称全称来获得jclass。如:jclass str = env->FindClass("java/lang/String")获得String的class对象
- GetObjectClass(jobject obj):通过对象实例来获取jclass,相当于java中的getClass方法
- GetSuperClass:获得父类的jclass对象。
调用方法的三种形式
- Call<Type>Method(jobject obj,jmethodID id,参数)
- Call<Type>Method(jobject obj,jmethodID id,va_list lst)
- Call<Type>Method(jobject obj,jmethodID id,jvalue* v)
第三种为jvalue的数组
jvalue * args = new jvalue[3]
args[0]=1
args[1] = 2.1
args[3] = "str"