ZBLOG

JNIEXPORT void JNICALL Java_com_ylkj_sdk_RknnWrapper_registerGestureResultCallback(JNIEnv *env, jclass, ...

您提供的代码段展示了如何在 JNI 中注册一个回调,以便 C++ 代码能够通过 Java 回调方法通知某些事件(如手势识别结果)。以下是对这段代码的逐行解析以及一些优化和注意事项:

代码解析

  1. 函数签名

    JNIEXPORT void JNICALL Java_com_ylkj_sdk_RknnWrapper_registerGestureResultCallback(JNIEnv *env, jclass, jobject callbackObj)
    
    • JNIEXPORTJNICALL 是用于标识 JNI 函数导出及调用约定。
    • 方法名称遵循 JNI 命名规则,表示它是从 com.ylkj.sdk.RknnWrapper 类调用的方法。
    • 接受三个参数:JNI 环境指针、类引用(未使用)、Java 回调对象。
  2. 获取回调对象的类信息和方法 ID

    jclass callbackClass = env->GetObjectClass(callbackObj);
    gestureResultMethodId = env->GetMethodID(callbackClass, "GestureResultCallBackFunc", "(Ljava/util/ArrayList;)V");
    gestureResultCallbackJobj = env->NewGlobalRef(callbackObj);
    
    • 使用 GetObjectClass 获取回调对象的类。
    • 使用 GetMethodID 获取要调用的方法 ID,这里假设这个方法接受一个 ArrayList 作为参数并返回 void
    • 将回调对象转换为全局引用以防止其被垃圾回收。
  3. 设置手势结果回调

    rknnEngine.SetGestureResultCallbackFunc([](const std::vector<obs_location_t> &locations){
        ...
    });
    
    • 在这里,您定义了一个 lambda 函数,该函数将在手势检测时被调用。
  4. 处理传入的数据

    JNIEnv* localEnv;
    jint getEnvResult = gvm->AttachCurrentThread(reinterpret_cast<JNIEnv**>(&localEnv), nullptr);
    if (getEnvResult == JNI_OK) {
        ...
        gvm->DetachCurrentThread();
    }
    
    • 您将当前线程附加到 JVM 以获取 JNIEnv。这在多线程环境中非常重要,因为每个线程都有自己的本地环境。
  5. 构建 ArrayList 并填充数据

     jobject locationListObj = localEnv->NewObject(arrayListCls, arrayListCtor);
     for (int i = 0; i < locations.size(); ++i) {
         obs_location_t location = locations.at(i);
         jobject locationObj = localEnv->NewObject(locationCls, locationCtor,
                                                   location.location,
                                                   location.exist_person,
                                                   location.raise_hand);
         localEnv->CallBooleanMethod(locationListObj, arrayListAddMethod, locationObj);
         localEnv->DeleteLocalRef(locationObj);
     }
    
    • 创建一个新的 ArrayList 实例,然后遍历 C++ 的位置向量,将每个元素添加到 Java 的数组列表中。
  6. 调用 Java 回调方法

     localEnv->CallVoidMethod(gestureResultCallbackJobj, gestureResultMethodId, locationListObj);
    
  7. 清理局部引用和分离线程: 在使用完本地引用后,通过 DeleteLocalRef() 清除,并在最后使用 DetachCurrentThread() 分离该线程。

注意事项与优化建议

  1. 错误处理:在实际应用中,你可能希望检查各个 JNI 调用是否成功,例如检查 GetMethodID, 创建全局引用等。这可以帮助你捕捉潜在问题并避免崩溃。

  2. 性能考量:尽量减少对 JNI 的频繁调用,因为跨语言边界会带来额外开销。考虑批处理或合并操作来提高性能。

  3. 内存管理:确保在不再需要全局引用时使用 DeleteGlobalRef() 来释放它们,以避免内存泄漏。

  4. 异常处理:JNI 调用后,可以检查是否抛出了异常,确保代码健壮性。例如,在调用方法之前检查:

if (localEnv->ExceptionCheck()) {
    // 处理异常
}

以上是关于您的代码段的一些分析和改进建议。如果有其他具体问题或场景,请告诉我!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=19766

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?