#鸿蒙通关秘籍#如何在非ArkTS线程中回调ArkTS接口?

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
墨香四溢EDIF

要在非ArkTS线程中回调ArkTS接口,可以利用napi_get_uv_event_loopuv_queue_work实现。具体步骤包括:

  1. 接口声明:为要实现的接口定义类型签名,例如:

    bash // index.d.ts export const queueWork: (cb: (arg: number) => void) => void;

  2. 编译配置:设置CMake编译配置,将必要的库链接到项目中。

    bash // CMakeLists.txt cmake_minimum_required(VERSION 3.4.1) project(MyApplication)

    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

    include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) add_library(queue_work SHARED queue_work.cpp) target_link_libraries(queue_work PUBLIC libace_napi.z.so libhilog_ndk.z.so libuv.so)

  3. 模块注册:在C++中注册模块并定义导出的接口。

    cpp // queue_work.cpp EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { { "queueWork", nullptr, QueueWork, nullptr, nullptr, nullptr, napi_default, nullptr } }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END

    static napi_module nativeModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "queue_work", .nm_priv = nullptr, .reserved = { 0 }, };

    extern "C" attribute((constructor)) void RegisterQueueWorkModule() { napi_module_register(&nativeModule); }

  4. 线程操作:定义处理异步任务和回调ArkTS的核心逻辑。

    cpp // queue_work.cpp #include <thread> #include "napi/native_api.h" #include "uv.h"

    struct CallbackContext { napi_env env = nullptr; napi_ref callbackRef = nullptr; int32_t retData = 0; };

    void StartThread(CallbackContext* context) { uv_loop_s* loop = nullptr; napi_get_uv_event_loop(context->env, &loop);

     uv_work_t* work = new uv_work_t;
     context->retData = 1;
     work->data = context;
    
     uv_queue_work(
         loop,
         work,
         [](uv_work_t* work) {},
         [](uv_work_t* work, int status) {
             CallbackContext* context = reinterpret_cast<CallbackContext*>(work->data);
             napi_handle_scope scope = nullptr;
             napi_open_handle_scope(context->env, &scope);
             if (scope == nullptr) {
                 return;
             }
    
             napi_value callback = nullptr;
             napi_get_reference_value(context->env, context->callbackRef, &callback);
             napi_value retArg;
             napi_create_int32(context->env, context->retData, &retArg);
             napi_value ret;
             napi_call_function(context->env, nullptr, callback, 1, &retArg, &ret);
             napi_delete_reference(context->env, context->callbackRef);
             napi_close_handle_scope(context->env, scope);
    
             if (work != nullptr) {
                 delete work;
             }
             delete context;
         }
     );
    

    }

    static napi_value QueueWork(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = {nullptr}; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);

     if (argc < 1) {
         napi_throw_error(env, "ParameterError", "one param expected");
         return nullptr;
     }
     napi_valuetype valueType = napi_undefined;
     napi_typeof(env, argv[0], &valueType);
     if (valueType != napi_function) {
         napi_throw_error(env, "ParameterError", "function expected");
         return nullptr;
     }
    
     auto asyncContext = new CallbackContext();
     asyncContext->env = env;
     napi_create_reference(env, argv[0], 1, &asyncContext->callbackRef);
     std::thread testThread(StartThread, asyncContext);
     testThread.detach();
    
     return nullptr;
    

    }

  5. ArkTS调用示例:在ArkTS中使用该接口。

    typescript import { queueWork } from 'libqueue_work.so'

    queueWork((result: number) => { console.log("result = " + result); });


分享
微博
QQ
微信
回复
2天前
相关问题
HarmonyOS ArkTS接口的案例
527浏览 • 1回复 待解决
HarmonyOS ArkTS接口的案例问题
551浏览 • 1回复 待解决
如何在ArkTS实现接口?
247浏览 • 1回复 待解决
如何在 ArkTS 定义和使用接口?
163浏览 • 0回复 待解决