c调用java方法_JNI中C调用Java方法

背景需求

我们需要在JNI的C代码调用Java代码。实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用。

JNI关键方法讲解。

1. 在同一个类中,调用其他方法

JNIEXPORT voidJNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod1

(JNIEnv*env, jobject obj){//在c代码里面调用java代码里面的方法//java 反射//1 . 找到java代码的 class文件//jclass (*FindClass)(JNIEnv*, const char*);

jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");if(dpclazz==0){

LOGI("find class error");return;

}

LOGI("find class");//2 寻找class里面的方法//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");if(method1==0){

LOGI("find method1 error");return;

}

LOGI("find method1");//3 .调用这个方法//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);

(*env)->CallVoidMethod(env,obj,method1);

}

注意: 看红色的内容,如何获得呢? 这个是函数的签名。函数签名借住命令 javap来获得,放到第二个参数即可。

20180920132332866814.png

这样就可以调用DataProvider中的helloFromJava方法了。

2. 上面的方法是调用的返回值为void的java方法。如果想调用其他类型的。JNI中还提供的许多其他返回类型的方法。

jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);

jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);

jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);

jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);

jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);

jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);

jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);

jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);

jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;

jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;

jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;

jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;

jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;

jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

3. 如果java中的方法是静态的,就需要调用GetStaticMethodID 和 CallStaticVoidMethod 方法。

JNIEXPORT voidJNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod4

(JNIEnv*env, jobject obj){//1 . 找到java代码的 class文件//jclass (*FindClass)(JNIEnv*, const char*);

jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");if(dpclazz==0){

LOGI("find class error");return;

}

LOGI("find class");//2 寻找class里面的方法//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//注意 :如果要寻找的方法是静态的方法 那就不能直接去获取methodid//jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");//jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);

jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");if(method4==0){

LOGI("find method4 error");return;

}

LOGI("find method4");//3.调用一个静态的java方法//void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);

(*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c"));

}

4. 如果C调用的Java方法不在一个类中。

分析:JNI提供的方法都有两个参数:(JNIEnv *env , jobject obj)。 env是JNI提供的方法集合。 obj是上线文。下面的例子的obj不是所需要的上下午,所以要重新创建。

//obj DemoActivity

JNIEXPORT voidJNICALL Java_cn_itcast_ndkcallback_DemoActivity_call_1dp_1method1

(JNIEnv*env, jobject obj){//在c代码里面调用java代码里面的方法//java 反射//1 . 找到java代码的 class文件//jclass (*FindClass)(JNIEnv*, const char*);

jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");if(dpclazz==0){

LOGI("find class error");return;

}

LOGI("find class");//2 寻找class里面的方法//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");if(method1==0){

LOGI("find method1 error");return;

}

LOGI("find method1");//3 .调用这个方法//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);//jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...);//jobject (*AllocObject)(JNIEnv*, jclass);

jobject dpobj= (*env)->AllocObject(env,dpclazz);

(*env)->CallVoidMethod(env,dpobj,method1);

}

5. 提示

为了避免4中的内容,我们尽量让C要调用的Java方法在同一个类中

原文:http://www.cnblogs.com/xitang/p/4174619.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值