JNI中C回调java方法

原理

C代码回调java方法的原理是利用反射的方法调用的。下面先简单介绍在java中利用反射调用方法的做法。

  • java工程中有一个业务类Utils,里面有一个test方法,在主类的Main方法中通过反射调用test方法。

  • Utils.java:


public class Utils {
    public void test(String s){
        System.out.println(s);
    }
}
  • Demo.java:
public class Demo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //1.0得到字节码对象
        Class clazz = Utils.class;
        try {
            //2.0获取Method对象
            Method method = clazz.getDeclaredMethod("test", String.class);
            //3.0通过字节码对象创建一个Object
            Object object = clazz.newInstance();
            //4.0通过对象调用方法
            method.invoke(object, "hello");
        } catch (Exception e) {
            e.printStackTrace();
        } 

    }

}

JNI中C代码回调java空方法

  • 在JNI类中声明一个java空方法和一个本地方法,然后在C中实现调用java空方法的逻辑。

  • C调用空方法的逻辑:

JNIEXPORT void JNICALL Java_com_zhong_callbackjava_JNI_callbackvoidmethod(
        JNIEnv * env, jobject clazz) {

    /*1.0获取字节码对象,jclass   (*FindClass)(JNIEnv*, const char*);
    第二个参数为所要回调java方法所在的类的路径。*/
    jclass claz = (*env)->FindClass(env, "com/zhong/callbackjava/JNI");

    /*2.0获取Method对象,jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    第二个参数为字节码对象,第三个参数为要反射调用的java方法名,第四个为java签名。*/
    jmethodID methodid = (*env)->GetMethodID(env, claz, "helloFromJava", "()V");
    /*3.0通过字节码对象创建一个Object,通过字节码创建 java对象(可选) 如果本地方法和要回调的java方法在同一个类里可以直接用 jni传过来的java对象(即clazz)调用创建的Method
    4.0通过对象调用方法, void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);*/
    (*env)->CallVoidMethod(env, clazz, methodid);
}

这里涉及一个得到java方法签名(即方法的形参)的方式,
这里写图片描述

JNI中C调用java中的带两个int参数的方法

JNIEXPORT void JNICALL Java_com_zhong_callbackjava_JNI_callbackintmethod(
        JNIEnv * env, jobject clazz) {
    jclass claz = (*env)->FindClass(env, "com/zhong/callbackjava/JNI");
    jmethodID methodid = (*env)->GetMethodID(env, claz, "add", "(II)I");
    int result = (*env)->CallIntMethod(env, clazz, methodid, 5, 8);
    LOGD("result = %d", result);
}

JNI中C调用java中参数为string的方法

JNIEXPORT void JNICALL Java_com_zhong_callbackjava_JNI_callbackstringmethod(
        JNIEnv * env, jobject clazz) {
    jclass claz = (*env)->FindClass(env, "com/zhong/callbackjava/JNI");
    jmethodID methodid = (*env)->GetMethodID(env, claz, "printString",
            "(Ljava/lang/String;)V");
    jstring result = (*env)->NewStringUTF(env, "hello form c!");
    (*env)->CallVoidMethod(env, clazz, methodid, result);
}

注意:

  • 第三步中通过字节码创建java对象时,当回调的方法跟本地方法不在一个类里 需要通过刚创建的字节码对象手动创建一个java对象,再通过这个对象来回调java的方法。需要注意的是 如果创建的是一个activity对象 回调的方法还包含上下文 这个方法行不通!!!会报空指针异常 。解决办法是在要调用的方法所在的类中增加构造方法传入上下文。
jobject obj =(*env)->AllocObject(env,claz);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值