[经验分享] Napi external 使用示例

深开鸿_苟晶晶 显示全部楼层 发表于 2024-11-26 11:35:16

简介

在处理大量数据时,为了避免在JavaScript和native层之间复制数据的性能开销,可以使用napi_create_external直接传递数据指针,并通过napi_get_value_external在需要时访问原始数据。本文以一个简单数组的传递介绍如何使用napi_create_external,napi_get_value_external。

文档环境

开发环境:Windows 10

DevEco Studio 版本:DevEco Studio 4.1 Release(4.1.0.400)

SDK 版本:API version 11 (4.1.7.5 Release)

开发板型号:DAYU200(RK3568)

OpenHarmony版本:OpenHarmony 5.0.2.51

使用示例

  1. 接口声明、编译配置、模块注册 接口声明

    export function createExternalArray(): object
    export function useExternalArray(arg: object): void

    编译配置

    cmake_minimum_required(VERSION 3.4.1)
    project(MyApplication2)
    
    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    
    include_directories(${NATIVERENDER_ROOT_PATH}
                        ${NATIVERENDER_ROOT_PATH}/include)
    
    add_library(entry SHARED external.cpp)
    target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)

    模块注册

    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
        napi_property_descriptor desc[] = {
            {"createExternalArray", nullptr, CreateExternalArray, nullptr, nullptr, nullptr, napi_default, nullptr},
            {"useExternalArray", nullptr, UseExternalArray, 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 = "entry",
        .nm_priv = nullptr,
        .reserved = { 0 },
    };
    extern "C" __attribute__((constructor)) void RegisterObjectWrapModule()
    {
        napi_module_register(&nativeModule);
    }
  2. 创建外部数据、获取外部数据

    // 外部数据的释放回调函数:当通过napi_create_external创建的外部值被垃圾回收时,会被调用以释放与之关联的原生资源。
    void FinalizeCallback(napi_env env, void* data, void* hint)
    {
        // 释放数组资源
        int32_t* cppArray = static_cast<int32_t*>(data);
        delete[] cppArray;
    }
    napi_value CreateExternalArray(napi_env env, napi_callback_info info)
    {
        int32_t* cppArray = new int32_t[5]{1, 2, 3, 4, 5};
        napi_status status;
        napi_value jsArray;
        // 创建一个 JavaScript 数组的外部引用
        status = napi_create_external(env, cppArray, FinalizeCallback, NULL, &jsArray);
        if (status != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "ARRAY", "napi_create_external_array fail.");
            return nullptr; // 处理错误
        }
        return jsArray; // 返回 JavaScript 数组
    }
    napi_value UseExternalArray(napi_env env, napi_callback_info info)
    {
        size_t argc = 1;
        napi_value args[1];
        int32_t* cppArraydata;
        napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
        // 获取外部数据
        napi_get_value_external(env, args[0], (void**)&cppArraydata);
        // 使用数组数据
        for (size_t i = 0; i < 5; i++) {
           OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "ARRAY", "napi_get_value_external array: %{public}d", cppArraydata[i]);
        }
        return nullptr;
    }
  3. ArkTS侧示例代码

    let res = testNapi.createExternalArray();
    testNapi.useExternalArray(res);
  4. 运行后,执行结果如下:

    18922-18922  A00000/ARRAY                   com.examp...lication  I     napi_get_value_external array: 1
    18922-18922  A00000/ARRAY                   com.examp...lication  I     napi_get_value_external array: 2
    18922-18922  A00000/ARRAY                   com.examp...lication  I     napi_get_value_external array: 3
    18922-18922  A00000/ARRAY                   com.examp...lication  I     napi_get_value_external array: 4
    18922-18922  A00000/ARRAY                   com.examp...lication  I     napi_get_value_external array: 5

    总结:这段代码展示了如何创建一个外部数组,将其传递给 JavaScript,并在需要时访问和使用这个数组。通过 napi_create_external 创建的外部值允许 JavaScript 层访问和操作 C++ 中的数据,而 napi_get_value_external 则用于在 native 层访问这些数据。这种机制使得在 JavaScript 和 native 层之间共享和操作数据变得更加灵活和高效。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部