JNI 接口回调

这篇博客介绍了如何使用JNI实现接口回调,通过Java层定义自定义Listener,C/C++层实现回调函数,实现异步调用的功能。文章跳过了JNI的基础知识,直接展示了Java层的接口定义、C++的实现以及Java调用native函数的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JNI 接口回调

这里主要演示从 Java 层传入自定义listener,然后由 c/c++ 层在某一时期某一线程主动调用 listener 的回调函数,完成异步回调的功能。
关于 jni 的其他部分基础知识本文不做详细介绍。

Java 层定义代码
  • java-native 函数以及接口定义

    package com.jnidemo;
    
    public class Greet {
    
        static {
            System.loadLibrary("jni_demo");
        }
    
        public native void native_say_hello(GreetListener listener);
    
        public interface GreetListener {
            /**
             * 这里为了演示自定义 Callback 的用法,使用了自定义 Java-Callback 类作为回调参数,
             * 可直接使用基本类型或者其他引用类型做回调参数,根据自己的业务需求决定。
             */
            void onGreetReceive(GreetCallback greet);
        }
    }
    
  • java 自定义 Callback 类

    package com.jnidemo;
    
    public class GreetCallback {
    
        private int greetID;
        private String greetMsg;
    
        public GreetCallback(int greetID, String greetMsg) {
            this.greetID = greetID;
            this.greetMsg = greetMsg;
        }
    }
    
c++ 层实现代码
  • 动态注册 native 实现函数

    const char *NATIVE_GREET_CLASS_NAME = "com/jnidemo/Greet";
    
    static JNINativeMethod gMethods_Greet[] = {
        {"native_say_hello", "(Lcom/jnidemo/Greet$GreetListener;)V", (void *)say_hello_jni}
    };
    
    static int registerNativeMethods(JNIEnv *env)
    {
        jclass clazz = env->FindClass(NATIVE_GREET_CLASS_NAME);
        if (clazz == NULL)
            return JNI_FALSE;
        if (env->RegisterNatives(clazz, gMethods_Greet, sizeof(gMethods_Greet) / sizeof(gMethods_Greet[0])) < 0)
            return JNI_FALSE;
        env->DeleteLocalRef(clazz);
        clazz = NULL;
        return JNI_TRUE;
    }
    
    jint JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        JNIEnv *env = NULL;
        if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
            return -1;
        assert(env != NULL);
        if (!registerNativeMethods(env))
            return -1;
    
        hover_jvm = vm;
        return JNI_VERSION_1_6;
    }
    
  • native 函数实现

    typedef struct
    {
        jobject o_greet_listener;
        jmethodID m_greet_receive;
    
        jclass z_greet_callback;
        jmethodID m_greet_callback_init;
    } jni_callback_t;
    
    // 定义承载 Java-Listener 和 Java-Callback 实例和 methodID 的结构体实例
    static jni_callback_t *jni_callback;
    
    /**
     * jni 动态注册对应的 native 实现函数。
     * 创建 Java-Listener 和 Java-Callback 的实例和 methodID 并赋值给 jni_callback_t.
     */
    static void say_hello_jni(JNIEnv *env, jobject object, jobject greet_listener)
    {
        if(!greet_listener)
            return;
    
        // 获得回调接口 函数onGreetReceive 的 methodID.
        jclass clazz_greet_listener = env->GetObjectClass(greet_listener);
        jmethodID method_greet_receive = env->GetMethodID(clazz_greet_listener, "onGreetReceive", "(Lcom/jnidemo/GreetCallback;)V");
    
        // 获得自定义 Callback类 GreetCallback 构造函数的 methodID.
        jclass clazz_greet_callback = env->FindClass("com/jnidemo/GreetCallback");
        jmethodID method_greet_callback_init = env->GetMethodID(clazz_greet_callback, "<init>", "(ILjava/lang/String;)V");
    
        // 这里创建 jni_callback_t 的实例,创建 Listener 和 Callback 的全局引用并赋值.
        jni_callback = (jni_callback_t *)malloc(sizeof(jni_callback_t));
        memset(jni_callback, 0, sizeof(jni_callback_t));
        jni_callback->o_greet_listener = env->NewGlobalRef(greet_listener);
        jni_callback->m_greet_receive = method_greet_receive;
        jni_callback->z_greet_callback = (jclass)env->NewGlobalRef(clazz_greet_callback);
        jni_callback->m_greet_callback_init = method_greet_callback_init;
    
        // 销毁局部引用
        env->DeleteLocalRef(clazz_greet_listener);
        env->DeleteLocalRef(clazz_greet_callback);
        clazz_greet_listener = NULL;
        clazz_greet_callback = NULL;
    
        // 这里创建子线程模拟异步回调
        pthread_t ntid;
        pthread_create(&ntid, NULL, async_thread_func, NULL);
    }
    
  • native 端子线程模拟回调

    void *async_thread_func(void *args)
    {
        // JNI_OnLoad 时保存 jvm,这里使用 jvm->AttachCurrentThread 获取 JNIEnv,暂不做详细介绍.
        JNIEnv *env = NULL;
        hover_attach_jni_env(&env);
    
        // 使用 java 构造函数生成 GreetCallback 的实例
        int greetID = 1;
        jstring greetMsg = env->NewStringUTF("say hi to java.");
        jobject greet_callback = env->NewObject(jni_callback->z_greet_callback, jni_callback->m_greet_callback_init, greetID, greetMsg);
    
        // 调用 GreetListener 的 onGreetReceive 函数,完成调用流程.
        env->CallVoidMethod(jni_callback->o_greet_listener, jni_callback->m_greet_receive, greet_callback);
    
        // 销毁局部引用
        env->DeleteLocalRef(greetMsg);
        env->DeleteLocalRef(greet_callback);
        greetMsg = NULL;
        greet_callback = NULL;
    
        // 销毁全局引用 --- 如果有多处或多次回调,自行判断销毁时机.
        env->DeleteGlobalRef(jni_callback->o_greet_listener);
        env->DeleteGlobalRef(jni_callback->z_greet_callback);
        jni_callback->o_greet_listener = NULL;
        jni_callback->z_greet_callback = NULL;
        free(jni_callback);
        jni_callback = NULL;
        
        return 0;
    }
    
Java 层调用 native 函数
  new Greet().native_say_hello(new Greet.GreetListener() {
          @Override
          public void onGreetReceive(GreetCallback greet) {
              Log.d(TAG, "hello, onGreetReceive: " + greet.toString());
          }
  });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值