鸿蒙 Node-API 自用整理

18 阅读27分钟

该文章主要用于后续node-api 调用时,进行功能查找使用;文章中可能存在部分问题,也希望各位大佬指正;

个人理解:Node-api 同 Android JNI一样主要用于应用层代码同 C++/C 代码进行交互的桥梁;主要用于将应用侧的数据转换为 c++/c 能理解的数据;或者将 c++/c数据通过 JNI转换为应用侧能理解的数据;

鸿蒙 NDK 相关文档地址developer.huawei.com/consumer/cn…

napi_status napi_get_cb_info

napi_status napi_get_cb_info(
    napi_env env,
    napi_callback_info cbinfo,
    size_t* argc,
    napi_value* argv,
    napi_value* thisArg,
    void** data
);
参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文,所有 NAPI 方法都需要传递此参数
cbinfo[in]napi_callback_info回调信息对象,由 Node-API 在调用原生函数时自动传入
argc[in-out]size_t*输入时:表示期望接收的最大参数数量 输出时:表示实际传入的参数数量 可传 nullptr 忽略
argv[out]napi_value*存储参数的数组,需预先分配足够内存 可传 nullptr 忽略
thisArg[out]napi_value*接收函数调用时的 this 对象 可传 nullptr 忽略
data[out]void**接收通过 napi_create_function 绑定的自定义数据 可传 nullptr 忽略

在平时的调用中一般仅仅设置前4个值;剩余两个传递nullptr 即可;

    如果调用该方法时不知道参数个数;可以设置期望值是0;然后再执行完api 后argc 就会得到真实的参数个数;注意:这个时候不用设置对应的 argv,直接传递 nullptr即可;因为当前还不知道固定参数的大小;

目的:在 TS 调用传递参数到 native 层的时候;用于对参数个数,以及参数进行接收;用于后面的使用做准备;一般用于第一步执行逻辑;

返回值:napi_status 用于判断结果是否正确;判断逻辑如下:

    if (status != napi_ok || argc < 1)// argc 是对应的参数个数;设置了一个参数判断几个
    {
        return "";//根据条件进行返回
    }

动态的获取参数数据:

#include "napi/native_api.h"

static napi_value DynamicTypeDemo(napi_env env, napi_callback_info info) {
    // 1. 先获取参数数量
    size_t argc = 0;
    napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);

    if (argc == 0) {
        return nullptr;
    }

    // 2. 动态分配数组并获取参数
    napi_value* args = new napi_value[argc];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 3. 遍历每个参数,动态判断类型
    for (size_t i = 0; i < argc; i++) {
        napi_valuetype type;
        napi_typeof(env, args[i], &type);

        switch (type) {
            case napi_undefined:
                // 处理 undefined 类型
                break;
            case napi_null:
                // 处理 null 类型
                break;
            case napi_boolean:
                // 处理 boolean 类型
                bool boolValue;
                napi_get_value_bool(env, args[i], &boolValue);
                break;
            case napi_number:
                // 处理 number 类型
                double numValue;
                napi_get_value_double(env, args[i], &numValue);
                break;
            case napi_string:
                // 处理 string 类型
                size_t strLen;
                napi_get_value_string_utf8(env, args[i], nullptr, 0, &strLen);
                // ... 获取字符串内容
                break;
            case napi_object:
                // 处理 object 类型
                // 可进一步判断是否为数组
                bool isArray;
                napi_is_array(env, args[i], &isArray);
                break;
            case napi_function:
                // 处理 function 类型(回调函数)
                break;
            default:
                break;
        }
    }

    delete[] args;
    return nullptr;
}

获取 this 对象模式:

static napi_value GetThisDemo(napi_env env, napi_callback_info info) {
    size_t argc = 0;
    napi_value thisArg = nullptr;
    napi_get_cb_info(env, info, &argc, nullptr, &thisArg, nullptr);

    // thisArg 即为调用该方法的对象
    return thisArg;
}

注意:这个对象获取的是TS 传递过来的对象 (用于调用方法的对象);同时这个地方就不用传递参数数据映射了,也就是第4个参数就是传递 nullptr;

注意:size_t argc = 5;napi_value argv[3] = {nullptr}; // 只有 3 个元素;在设置第2,3个参数时;数量不能设置不匹配否则就会出现越界;

napi_typeof(env, args[0], &valuetype0);

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
value[in]napi_value要获取类型的 JavaScript 值
result[out]napi_valuetype*输出参数,用于接收类型枚举值
返回值

返回 napi_status 枚举值,表示操作结果:

返回值说明
napi_ok成功获取类型
napi_invalid_arg参数无效(如 envvalue 或 result 为 nullptr
napi_valuetype 枚举值
类型枚举对应 ArkTS 类型
napi_undefinedundefined
napi_nullnull
napi_booleanboolean
napi_numbernumber
napi_stringstring
napi_symbolsymbol
napi_objectobject
napi_functionfunction
napi_external外部数据
napi_bigintbigint
   // 校验参数是否为函数
    if (type != napi_function) {
        napi_throw_type_error(env, nullptr, "Argument must be a function");
        return nullptr;
    }

napi_status napi_get_value_string_utf8

napi_status napi_get_value_string_utf8(napi_env env, napi_value value, char* buf, size_t bufsize, size_t* result);

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
value[in]napi_value要获取的 JavaScript 字符串值(必须是 string 类型
buf[in]char*用于存储字符串的缓冲区指针
bufsize[in]size_t缓冲区大小(字节)
result[out]size_t*输出参数,返回实际写入/复制的字节数(不含 null 终止符
返回值
返回值说明
napi_ok成功获取字符串
napi_string_expectedvalue 不是字符串类型
napi_invalid_arg参数无效
获取字符串长度
// 传入 buf = nullptr, bufsize = 0
// result 将返回字符串的字节长度(不含 null 终止符)
size_t strLen = 0;
napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen);
获取字符串内容
// 传入有效的缓冲区
char* buf = new char[strLen + 1];  // +1 用于存储 null 终止符
napi_get_value_string_utf8(env, args[0], buf, strLen + 1, &strLen);
// buf 现在包含字符串内容
动态分配内存获取字符串
#include "napi/native_api.h"
#include <cstring>

static napi_value GetStringDemo(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 1. 校验参数是否为字符串类型
    napi_valuetype type;
    napi_typeof(env, args[0], &type);
    if (type != napi_string) {
        napi_throw_type_error(env, nullptr, "Argument must be a string");
        return nullptr;
    }

    // 2. 获取字符串长度
    size_t strLen = 0;
    napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen);
    if (status != napi_ok) {
        return nullptr;
    }
    // 3. 分配缓冲区(+1 用于 null 终止符)
    char* buf = new char[strLen + 1];
    // 4. 获取字符串内容
    size_t copiedLen = 0;
    status = napi_get_value_string_utf8(env, args[0], buf, strLen + 1, &copiedLen);

    if (status == napi_ok) {
        // 使用字符串
        // buf[strLen] = '\0';  // 已经自动添加了 null 终止符
    }

    // 5. 释放内存
    delete[] buf;

    return nullptr;
}
示例二:使用固定大小缓冲区
static napi_value GetFixedString(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 使用固定大小的缓冲区
    char buf[256];
    size_t copiedLen = 0;

    napi_status status = napi_get_value_string_utf8(env, args[0], buf, sizeof(buf), &copiedLen);

    if (status == napi_ok) {
        // 如果字符串长度超过 255,会被截断
        // copiedLen 返回实际复制的字节数
    }

    return nullptr;
}
示例三:转换为 std::string
#include <string>

static napi_value ConvertToStdString(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取长度
    size_t strLen = 0;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen);

    // 分配并获取内容
    char* buf = new char[strLen + 1];
    napi_get_value_string_utf8(env, args[0], buf, strLen + 1, &strLen);

    // 转换为 std::string
    std::string cppStr(buf);

    delete[] buf;

    // 使用 cppStr...

    return nullptr;
}
重要注意事项
注意点说明
null 终止符函数会自动在字符串末尾添加 \0,缓冲区大小需要 strLen + 1
字节长度strLen 返回的是字节长度,不是字符数(UTF-8 中多字节字符占多个字节
截断行为如果 bufsize 小于字符串长度,字符串会被截断
类型检查调用前应确保 value 是字符串类型,否则返回 napi_string_expected
内存管理动态分配的缓冲区需要手动释放,避免内存泄漏

napi_get_value_double 参数详解

napi_status napi_get_value_double(napi_env env, napi_value value, double* result);

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
value[in]napi_value要获取的 JavaScript 数值(必须是 number 类型
result[out]double*输出参数,用于存储获取到的 double 值
返回值
返回值说明
napi_ok成功获取数值
napi_number_expectedvalue 不是数字类型
napi_invalid_arg参数无效(如 result 为 nullptr

基础用法:

#include "napi/native_api.h"

static napi_value GetDoubleDemo(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取 double 值
    double value = 0.0;
    napi_status status = napi_get_value_double(env, args[0], &value);

    if (status != napi_ok) {
        // 处理错误
        return nullptr;
    }

    // 使用 value...

    return nullptr;
}
相关函数对比
函数C++ 类型JavaScript 类型说明
napi_get_value_doubledoublenumber获取双精度浮点数
napi_get_value_int32int32_tnumber获取 32 位整数(会截断小数)
napi_get_value_uint32uint32_tnumber获取无符号 32 位整数
napi_get_value_int64int64_tnumber获取 64 位整数
napi_get_value_bigint_int64int64_tbigint从 BigInt 获取 64 位整数
napi_get_value_bigint_uint64uint64_tbigint从 BigInt 获取无符号 64 位整数
注意事项
注意点说明
精度JavaScript 的 number 类型是 IEEE 754 双精度浮点数,与 C++ double 一一对应
类型检查如果传入非数字类型,返回 napi_number_expected
整数截断如需整数,建议使用 napi_get_value_int32 或 napi_get_value_int64
NaN 和 Infinity可以正确获取 NaNInfinity-Infinity 等特殊值

napi_create_string_utf8 参数详解

napi_status napi_create_string_utf8(napi_env env, const char* str, size_t length, napi_value* result);

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
str[in]const char*C 风格字符串指针(UTF-8 编码)
length[in]size_t字符串的字节长度(不含 null 终止符)
result[out]napi_value*输出参数,用于存储创建的 JavaScript 字符串
返回值
返回值说明
napi_ok成功创建字符串
napi_invalid_arg参数无效(如 str 或 result 为 nullptr
从 C 字符串创建
#include "napi/native_api.h"

static napi_value CreateStringDemo(napi_env env, napi_callback_info info) {
    const char* cStr = "Hello, HarmonyOS!";

    // 创建 JavaScript 字符串
    napi_value result;
    napi_status status = napi_create_string_utf8(env, cStr, strlen(cStr), &result);

    if (status != napi_ok) {
        return nullptr;
    }

    return result;
}
从 std::string 创建
#include <string>

static napi_value CreateFromString(napi_env env, napi_callback_info info) {
    std::string cppStr = "Hello from C++";

    napi_value result;
    napi_status status = napi_create_string_utf8(
        env, 
        cppStr.c_str(),   // 转换为 const char*
        cppStr.length(),  // 字节长度
        &result
    );

    if (status != napi_ok) {
        return nullptr;
    }

    return result;
}
使用 NAPI_AUTO_LENGTH
static napi_value CreateWithAutoLength(napi_env env, napi_callback_info info) {
    const char* str = "Hello";

    napi_value result;
    // NAPI_AUTO_LENGTH 表示字符串以 null 结尾,自动计算长度
    napi_status status = napi_create_string_utf8(
        env, 
        str, 
        NAPI_AUTO_LENGTH,  // 自动计算长度
        &result
    );

    return result;
}
Length 参数详解
方式说明
strlen(str)手动计算字节长度
NAPI_AUTO_LENGTH自动计算(字符串必须以 \0 结尾)
cppStr.length()从 std::string 获取长度
相关函数对比
函数编码说明
napi_create_string_utf8UTF-8创建 UTF-8 编码字符串
napi_create_string_latin1Latin-1创建 Latin-1 编码字符串(仅支持单字节字符)
napi_create_string_utf16UTF-16创建 UTF-16 编码字符串
注意事项
注意点说明
字节长度length 是字节长度,不是字符数(UTF-8 中文字符占 3 字节)
null 终止符length 不包含 \0 终止符
编码要求字符串必须是有效的 UTF-8 编码
内存管理创建后 JavaScript 引擎会复制字符串,原字符串可立即释放
NAPI_AUTO_LENGTH使用时确保字符串以 \0 结尾
napi_create_double 参数详解

napi_status napi_create_double(napi_env env, double value, napi_value* result);

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
value[in]double要转换的 C++ 双精度浮点数
result[out]napi_value*输出参数,用于存储创建的 JavaScript number 值
返回值
返回值说明
napi_ok成功创建数值
napi_invalid_arg参数无效(如 result 为 nullptr
基本用法
#include "napi/native_api.h"

static napi_value CreateDoubleDemo(napi_env env, napi_callback_info info) {
    double value = 3.14159;

    // 创建 JavaScript number
    napi_value result;
    napi_status status = napi_create_double(env, value, &result);

    if (status != napi_ok) {
        return nullptr;
    }

    return result;
}
相关创建函数对比
函数C++ 类型JavaScript 类型说明
napi_create_doubledoublenumber创建双精度浮点数
napi_create_int32int32_tnumber创建 32 位整数
napi_create_uint32uint32_tnumber创建无符号 32 位整数
napi_create_int64int64_tnumber创建 64 位整数
napi_create_bigint_int64int64_tbigint创建 64 位 BigInt
napi_create_bigint_uint64uint64_tbigint创建无符号 64 位 BigInt
注意事项
注意点说明
精度JavaScript number 与 C++ double 精度一致(IEEE 754 双精度)
特殊值可正确处理 NaNInfinity-Infinity
整数优化如确定是整数,可用 napi_create_int32 或 napi_create_int64
大整数超过 53 位精度的整数应使用 BigInt 相关函数
napi_set_named_property 参数详解

napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, napi_value value);

目的:给参数里的 obj 对象,挂载指定名称的属性和值。(其实就是将需要数据封装成 obj 对象传递个 TS层)

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
object[in]napi_value要设置属性的 JavaScript 对象
utf8name[in]const char*属性名称(UTF-8 编码的 C 字符串)
value[in]napi_value要设置的属性值
返回值
返回值说明
napi_ok成功设置属性
napi_invalid_arg参数无效(如 object 不是对象)
创建对象并设置基本属性
#include "napi/native_api.h"

static napi_value CreateObjectDemo(napi_env env, napi_callback_info info) {
    // 1. 创建空对象
    napi_value obj;
    napi_create_object(env, &obj);

    // 2. 创建各种类型的值
    napi_value numVal;
    napi_value strVal;
    napi_value boolVal;

    napi_create_double(env, 3.14, &numVal);
    napi_create_string_utf8(env, "Hello", NAPI_AUTO_LENGTH, &strVal);
    napi_get_boolean(env, true, &boolVal);

    // 3. 设置属性
    napi_set_named_property(env, obj, "number", numVal);
    napi_set_named_property(env, obj, "string", strVal);
    napi_set_named_property(env, obj, "boolean", boolVal);

    return obj;
}
相关函数对比
函数属性名类型说明
napi_set_named_propertyconst char*使用 UTF-8 字符串作为属性名
napi_set_propertynapi_value使用 napi_value 作为属性名(可以是任意类型)

napi_get_named_property 参数详解

napi_status napi_get_named_property(napi_env env, napi_value object, const char* utf8name, napi_value* result);

  • 使用场景

    C++ Native 层拿到 TS/JS 传过来的对象,按字段名提取数据

  • 读写配对

    • 存属性:napi_set_named_property(C++ 给对象加字段)
    • 取属性:napi_get_named_property(C++ 从对象读字段)
参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
object[in]napi_value要获取属性的 JavaScript 对象
utf8name[in]const char*属性名称(UTF-8 编码的 C 字符串)
result[out]napi_value*输出参数,用于存储获取到的属性值
返回值
返回值说明
napi_ok成功获取属性
napi_invalid_arg参数无效(如 object 不是对象、result 为 nullptr
基本用法
#include "napi/native_api.h"

static napi_value GetPropertyDemo(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取对象中的属性
    napi_value value;
    napi_status status = napi_get_named_property(env, args[0], "myProperty", &value);

    if (status != napi_ok) {
        return nullptr;
    }

    return value;
}
获取并转换数值属性
static napi_value GetNumberProperty(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取属性值
    napi_value propValue;
    napi_get_named_property(env, args[0], "count", &propValue);

    // 转换为 double
    double count = 0.0;
    napi_get_value_double(env, propValue, &count);

    // 返回处理后的值
    napi_value result;
    napi_create_double(env, count * 2, &result);

    return result;
}
获取多个属性
static napi_value GetMultipleProperties(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取多个属性
    napi_value xVal, yVal, zVal;
    napi_get_named_property(env, args[0], "x", &xVal);
    napi_get_named_property(env, args[0], "y", &yVal);
    napi_get_named_property(env, args[0], "z", &zVal);

    // 转换为 double
    double x = 0.0, y = 0.0, z = 0.0;
    napi_get_value_double(env, xVal, &x);
    napi_get_value_double(env, yVal, &y);
    napi_get_value_double(env, zVal, &z);

    // 计算结果
    double sum = x + y + z;

    // 返回结果
    napi_value result;
    napi_create_double(env, sum, &result);

    return result;
}
获取嵌套对象属性
static napi_value GetNestedProperty(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取嵌套对象
    napi_value inner;
    napi_get_named_property(env, args[0], "inner", &inner);

    // 获取嵌套对象中的属性
    napi_value value;
    napi_get_named_property(env, inner, "value", &value);

    return value;
}
检查属性是否存在
static napi_value GetPropertySafely(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 检查属性是否存在
    bool hasProperty = false;
    napi_value key;
    napi_create_string_utf8(env, "myProperty", NAPI_AUTO_LENGTH, &key);
    napi_has_property(env, args[0], key, &hasProperty);

    if (!hasProperty) {
        // 属性不存在,返回默认值
        napi_value defaultValue;
        napi_get_undefined(env, &defaultValue);
        return defaultValue;
    }

    // 获取属性值
    napi_value value;
    napi_get_named_property(env, args[0], "myProperty", &value);

    return value;
}
获取数组属性
static napi_value GetArrayProperty(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取数组属性
    napi_value arr;
    napi_get_named_property(env, args[0], "numbers", &arr);

    // 确认是数组
    bool isArray = false;
    napi_is_array(env, arr, &isArray);

    if (!isArray) {
        return nullptr;
    }

    // 获取数组长度
    uint32_t length = 0;
    napi_get_array_length(env, arr, &length);

    // 遍历数组计算总和
    double sum = 0.0;
    for (uint32_t i = 0; i < length; i++) {
        napi_value element;
        napi_get_element(env, arr, i, &element);

        double num = 0.0;
        napi_get_value_double(env, element, &num);
        sum += num;
    }

    // 返回总和
    napi_value result;
    napi_create_double(env, sum, &result);

    return result;
}
相关函数对比
函数属性名类型说明
napi_get_named_propertyconst char*使用 UTF-8 字符串作为属性名
napi_get_propertynapi_value使用 napi_value 作为属性名
检查属性是否存在
函数说明
napi_has_named_property检查命名属性是否存在
napi_has_property检查属性是否存在(使用 napi_value 作为键)
static napi_value CheckPropertyDemo(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 检查属性是否存在
    bool hasProp = false;
    napi_has_named_property(env, args[0], "myProperty", &hasProp);

    napi_value result;
    napi_get_boolean(env, hasProp, &result);

    return result;
}

napi_call_function 参数详解

napi_status napi_call_function(napi_env env, napi_value this_arg, napi_value func, size_t argc, const napi_value* argv, napi_value* result);

常用场景

  1. TS 把回调函数传给 Native,Native 做完任务后回调 TS(最常见);
  2. Native 主动加载 TS 模块,调用模块里的导出函数。
参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
this_arg[in]napi_value函数调用时的 this 值
func[in]napi_value要调用的 JavaScript 函数
argc[in]size_t参数个数
argv[in]const napi_value*参数数组指针
result[out]napi_value*输出参数,存储函数返回值
返回值
返回值说明
napi_ok成功调用函数
napi_function_expectedfunc 不是函数类型
napi_invalid_arg参数无效
this_arg 参数
场景传入值说明
普通函数调用undefined 或 null相当于 func.call(null, ...)
对象方法调用对象本身相当于 obj.method.call(obj, ...)
构造函数调用不适用(使用 napi_new_instance创建新实例
无参数调用
#include "napi/native_api.h"

static napi_value CallNoArgs(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // args[0] 是回调函数
    napi_value undefined;
    napi_get_undefined(env, &undefined);

    // 调用无参数函数
    napi_value result;
    napi_status status = napi_call_function(env, undefined, args[0], 0, nullptr, &result);

    if (status != napi_ok) {
        return nullptr;
    }

    return result;
}
带参数调用
static napi_value CallWithArgs(napi_env env, napi_callback_info info) {
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // args[0] 是回调函数
    // args[1], args[2] 是要传递的参数

    napi_value undefined;
    napi_get_undefined(env, &undefined);

    // 准备参数数组
    napi_value callArgs[2] = {args[1], args[2]};

    // 调用函数,传入 2 个参数
    napi_value result;
    napi_call_function(env, undefined, args[0], 2, callArgs, &result);

    return result;
}
调用并获取返回值
static napi_value CallAndProcessResult(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // args[0] 是回调函数
    // args[1] 是参数

    napi_value undefined;
    napi_get_undefined(env, &undefined);

    // 调用函数
    napi_value callArgs[1] = {args[1]};
    napi_value result;
    napi_status status = napi_call_function(env, undefined, args[0], 1, callArgs, &result);

    if (status != napi_ok) {
        // 调用失败
        return nullptr;
    }

    // 处理返回值
    napi_valuetype type;
    napi_typeof(env, result, &type);

    if (type == napi_number) {
        double num = 0.0;
        napi_get_value_double(env, result, &num);
        // 处理数字...
    }

    return result;
}
调用对象方法
static napi_value CallObjectMethod(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // args[0] 是对象

    // 获取对象的方法
    napi_value method;
    napi_get_named_property(env, args[0], "myMethod", &method);

    // 检查是否为函数
    napi_valuetype type;
    napi_typeof(env, method, &type);

    if (type != napi_function) {
        napi_throw_type_error(env, nullptr, "myMethod is not a function");
        return nullptr;
    }

    // 调用方法,this 指向对象本身
    napi_value result;
    napi_call_function(env, args[0], method, 0, nullptr, &result);

    return result;
}
export interface MyObject {
  myMethod(): void;
}

/**
 * 调用对象的 myMethod 方法
 * @param obj - 包含 myMethod 方法的对象
 */
export const callObjectMethod: (obj: MyObject) => void;


调用:
     Button('调用对象方法')
        .onClick(() => {
          // 定义包含 myMethod 的对象
          const myObj = {
            myMethod: () => {
              console.log('myMethod 被调用了!');
            }
          };

          // 调用 Native 方法
          callObjectMethod(myObj);
        });

napi_create_function 参数详解

napi_status napi_create_function(
  napi_env env,          // NAPI 运行环境
  const char* utf8name, // 函数名称(调试/栈追踪用)
  size_t length,        // 函数名字符串长度,传 NAPI_AUTO_LENGTH 自动计算
  napi_callback cb,     // 【核心】C++ 回调函数,函数实际逻辑写在这里
  void* data,           // 自定义上下文数据,会透传给 cb 回调,无需求传 nullptr
  napi_value* result    // 输出:创建好的 JS 函数对象(napi_value)
);

****作用:****napi_create_function在 Native (C/C++) 里创建一个可被 JS/TS 调用的函数对象,用于把 C++ 逻辑暴露成 TS/JS 可直接调用的方法

参数含义
参数方向类型说明
env[in]napi_env当前 NAPI 执行环境上下文
utf8name[in]const char*函数名称(UTF-8 编码),可为 nullptr
length[in]size_t函数名称的字节长度,可使用 NAPI_AUTO_LENGTH
cb[in]napi_callbackC++ 回调函数指针
data[in]void*用户自定义数据,传递给回调函数
result[out]napi_value*输出参数,存储创建的 JavaScript 函数
返回值
返回值说明
napi_ok成功创建函数
napi_invalid_arg参数无效(如 cb 或 result 为 nullptr
napi_callback 类型定义
typedef napi_value (*napi_callback)(napi_env env, napi_callback_info info);

回调函数签名:

  • 参数 env:NAPI 环境上下文
  • 参数 info:回调信息,可通过 napi_get_cb_info 获取参数
  • 返回值:函数的返回值(napi_value
基本用法
#include "napi/native_api.h"

// 回调函数实现
static napi_value MyCallback(napi_env env, napi_callback_info info) {
    // 获取参数
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 处理并返回
    double value = 0.0;
    napi_get_value_double(env, args[0], &value);

    napi_value result;
    napi_create_double(env, value * 2, &result);

    return result;
}

// 创建函数
static napi_value CreateFunctionDemo(napi_env env, napi_callback_info info) {
    napi_value func;
    napi_status status = napi_create_function(
        env,                    // 环境上下文
        "doubleIt",             // 函数名
        NAPI_AUTO_LENGTH,       // 自动计算名称长度
        MyCallback,             // 回调函数
        nullptr,                // 用户数据
        &func                   // 输出:创建的函数
    );

    if (status != napi_ok) {
        return nullptr;
    }

    // 返回创建的函数
    return func;
}
使用用户数据
// 用户数据结构
typedef struct {
    double multiplier;
    const char* name;
} UserData;

// 回调函数
static napi_value MultiplyCallback(napi_env env, napi_callback_info info) {
    // 获取用户数据
    void* data = nullptr;
    napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data);

    UserData* userData = (UserData*)data;

    // 获取参数
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    double value = 0.0;
    napi_get_value_double(env, args[0], &value);

    // 使用用户数据进行计算
    double result = value * userData->multiplier;

    napi_value jsResult;
    napi_create_double(env, result, &jsResult);

    return jsResult;
}

// 创建带用户数据的函数
static napi_value CreateMultiplyFunction(napi_env env, napi_callback_info info) {
    // 准备用户数据
    static UserData data = { 3.0, "triple" };

    napi_value func;
    napi_create_function(
        env,
        "triple",
        NAPI_AUTO_LENGTH,
        MultiplyCallback,
        &data,          // 传递用户数据
        &func
    );

    return func;
}
匿名函数(无名称)
static napi_value SimpleCallback(napi_env env, napi_callback_info info) {
    napi_value result;
    napi_create_double(env, 42, &result);
    return result;
}

static napi_value CreateAnonymousFunction(napi_env env, napi_callback_info info) {
    napi_value func;
    napi_create_function(
        env,
        nullptr,            // 匿名函数,无名称
        0,
        SimpleCallback,
        nullptr,
        &func
    );

    return func;
}
创建并调用函数
static napi_value AddCallback(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    double a = 0.0, b = 0.0;
    napi_get_value_double(env, args[0], &a);
    napi_get_value_double(env, args[1], &b);

    napi_value result;
    napi_create_double(env, a + b, &result);

    return result;
}

static napi_value CreateAndCall(napi_env env, napi_callback_info info) {
    // 1. 创建函数
    napi_value addFunc;
    napi_create_function(env, "add", NAPI_AUTO_LENGTH, AddCallback, nullptr, &addFunc);

    // 2. 准备参数
    napi_value a, b;
    napi_create_double(env, 10, &a);
    napi_create_double(env, 20, &b);

    napi_value args[2] = {a, b};

    // 3. 调用函数
    napi_value undefined;
    napi_get_undefined(env, &undefined);

    napi_value result;
    napi_call_function(env, undefined, addFunc, 2, args, &result);

    return result;  // 返回 30
}
将函数作为对象方法
static napi_value GetNameCallback(napi_env env, napi_callback_info info) {
    napi_value result;
    napi_create_string_utf8(env, "MyObject", NAPI_AUTO_LENGTH, &result);
    return result;
}

static napi_value GetValueCallback(napi_env env, napi_callback_info info) {
    napi_value result;
    napi_create_double(env, 100.0, &result);
    return result;
}

static napi_value CreateObjectWithMethods(napi_env env, napi_callback_info info) {
    // 创建对象
    napi_value obj;
    napi_create_object(env, &obj);

    // 创建方法函数
    napi_value getName, getValue;
    napi_create_function(env, "getName", NAPI_AUTO_LENGTH, GetNameCallback, nullptr, &getName);
    napi_create_function(env, "getValue", NAPI_AUTO_LENGTH, GetValueCallback, nullptr, &getValue);

    // 将函数设置为对象属性
    napi_set_named_property(env, obj, "getName", getName);
    napi_set_named_property(env, obj, "getValue", getValue);

    return obj;
}
函数工厂模式
// 通用的乘法回调
static napi_value MultiplierCallback(napi_env env, napi_callback_info info) {
    void* data = nullptr;
    napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data);

    double multiplier = *(double*)data;

    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    double value = 0.0;
    napi_get_value_double(env, args[0], &value);

    napi_value result;
    napi_create_double(env, value * multiplier, &result);

    return result;
}

// 工厂函数:创建指定倍数的乘法函数
static napi_value CreateMultiplier(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    double multiplier = 0.0;
    napi_get_value_double(env, args[0], &multiplier);

    // 注意:需要管理 multiplier 的生命周期
    double* data = new double(multiplier);

    napi_value func;
    napi_create_function(
        env,
        "multiply",
        NAPI_AUTO_LENGTH,
        MultiplierCallback,
        data,
        &func
    );

    return func;
}

区别:在.d.ts 文件中创建方法调用和通过napi_create_function创建方法;

────────────────────────────────────────────────────────────────────────┐
│                        静态导出(常用)                                │
├────────────────────────────────────────────────────────────────────────┤
│  C++: napi_define_properties() 导出固定方法                           │
│  TS:  直接调用 import { add } from 'libentry'                        │
│  场景: 模块的基础功能方法                                              │
│  是否需要 napi_create_function: ❌ 不需要                             │
└────────────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────────────┐
│                        动态创建函数(特殊场景)                        │
├────────────────────────────────────────────────────────────────────────┤
│  C++: napi_create_function() 运行时创建函数                           │
│  TS:  接收函数作为返回值,如 createMultiplier(2)                      │
│  场景: 函数工厂、高阶函数、动态方法                                    │
│  是否需要 napi_create_function: ✅ 需要       

napi_get_element

napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value* result);

参数含义
参数类型方向说明
envnapi_env[in]调用 API 的环境上下文
objectnapi_value[in]要从中获取元素的 ArkTS 数组对象
indexuint32_t[in]要获取的元素的索引位置
resultnapi_value*[out]获取到的元素值,通过此参数返回

返回 napi_status 枚举值,表示操作状态:

  • napi_ok:操作成功
  • napi_object_expected:当参数 object 不是 Object 或 Function 对象时返回
  • 其他错误码表示相应的错误情况
注意事项
  • 请求索引值应在数组的有效范围内
  • 如果索引超出数组长度,函数会返回 undefined
1. C++ 侧实现
#include "napi/native_api.h"

// 使用 Node-API 接口进行 array 相关开发 napi_get_element
static napi_value NapiGetElement(napi_env env, napi_callback_info info)
{
    // 获取 ArkTS 侧传入的参数
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取请求元素的索引值
    uint32_t index;
    napi_get_value_uint32(env, args[1], &index);

    // 获取请求索引位置的元素值并存储在 result 中
    napi_value result;
    napi_get_element(env, args[0], index, &result);

    return result;
}
2. 接口声明 (index.d.ts)
export const napiGetElement: <T>(arr: Array<T>, index: number) => number | string | Object | boolean | undefined;
3. ArkTS 侧调用示例
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';

// 定义接口类型
interface MyObject {
    first: number;
    second: number;
}

// 创建测试数据
let obj: MyObject = {
    first: 1,
    second: 2
};

let arr = [10, 'hello', null, obj];

// 获取不同类型的元素
hilog.info(0x0000, 'testTag', 'arr[0]: %{public}d', 
    testNapi.napiGetElement<number | string | null | Object>(arr, 0));

hilog.info(0x0000, 'testTag', 'arr[1]: %{public}s', 
    testNapi.napiGetElement<number | string | null | Object>(arr, 1));

hilog.info(0x0000, 'testTag', 'arr[2]: %{public}s', 
    testNapi.napiGetElement<number | string | null | Object>(arr, 2));

hilog.info(0x0000, 'testTag', 'arr[3]: %{public}s', 
    testNapi.napiGetElement<number | string | null | Object>(arr, 3));

// 索引超出范围时返回 undefined
hilog.info(0x0000, 'testTag', 'arr[4]: %{public}s', 
    JSON.stringify(testNapi.napiGetElement(arr, 4)));
相关接口
接口描述
napi_set_element在数组指定索引处设置元素值
napi_has_element判断数组指定索引处是否包含元素
napi_delete_element删除数组指定索引处的元素
napi_get_array_length获取数组长度

napi_set_element

napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value);

参数说明
参数类型说明
envnapi_envNode-API 执行时的上下文环境
objectnapi_value目标对象(数组或支持索引访问的对象)
indexuint32_t要设置的元素索引位置
valuenapi_value要设置的值
返回值

返回 napi_status 枚举值,表示操作是否成功:

  • napi_ok:操作成功
  • napi_object_expected:当参数 object 不是 Object 或 Function 对象时返回
C++ 侧代码
#include "napi/native_api.h"

static constexpr int INT_ARG_2 = 2; // 入参索引

// napi_set_element
static napi_value NapiSetElement(napi_env env, napi_callback_info info)
{
    // 获取ArkTS侧传入的参数
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 检查第一个参数是否为数组
    bool isArr = false;
    napi_is_array(env, args[0], &isArr);
    if (!isArr) {
        napi_throw_type_error(env, nullptr, "Argument should be an object of type array");
        return nullptr;
    }

    // 获取要设置的元素索引
    double index = 0;
    napi_get_value_double(env, args[1], &index);

    // 将传入的值设置到数组指定索引位置
    napi_set_element(env, args[0], static_cast<uint32_t>(index), args[INT_ARG_2]);

    return nullptr;
}
接口声明
export const napiSetElement: <T>(arr: Array<T>, index: number, value: T) => void;
ArkTS 侧示例代码
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';

// napi_set_element
try {
    let arr = [10, 20, 30];
    testNapi.napiSetElement<number | string>(arr, 1, 'newElement');
    testNapi.napiSetElement<number | string>(arr, 2, 50);
    hilog.info(0x0000, 'testTag', 'Test Node-API napi_set_element arr: %{public}s', arr.toString());

    // 设置对象类型的元素
    interface MyObject {
        first: number;
        second: number;
    }
    let obj: MyObject = {
        first: 1,
        second: 2
    };
    testNapi.napiSetElement<number | string | Object>(arr, 4, obj);
    let objAsString = JSON.stringify(arr[4]);
    hilog.info(0x0000, 'testTag', 'Test Node-API napi_set_element arr[4]: %{public}s', objAsString);
} catch (error) {
    hilog.error(0x0000, 'testTag', 'Test Node-API napi_set_element error: %{public}s', error.message);
}

napi_create_array

napi_create_array 是 Node-API 提供的接口,用于在 Native 层创建一个空的 ArkTS 数组对象。

napi_status napi_create_array(napi_env env, napi_value* result);

参数说明
参数类型说明
envnapi_envNode-API 执行时的上下文环境
resultnapi_value*出参,用于接收创建的数组对象
返回值

返回 napi_status 枚举值,表示操作是否成功:

  • napi_ok:操作成功
C++ 侧代码
#include "napi/native_api.h"

static constexpr int INT_NUM_5 = 5; // 数组长度

// napi_create_array
static napi_value CreateArray(napi_env env, napi_callback_info info)
{
    // 创建一个空数组
    napi_value jsArray = nullptr;
    napi_create_array(env, &jsArray);

    // 将创建好的数组进行赋值
    for (int i = 0; i < INT_NUM_5; i++) {
        napi_value element;
        napi_create_int32(env, i, &element);
        napi_set_element(env, jsArray, i, element);
    }

    // 返回已创建好的数组
    return jsArray;
}
接口声明
export const createArray: () => number[];
ArkTS 侧示例代码
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';

// napi_create_array
hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_array:%{public}s', 
    JSON.stringify(testNapi.createArray()));
相关接口
接口功能说明
napi_create_array创建一个空的 ArkTS Array
napi_create_array_with_length创建一个指定长度的 ArkTS Array
napi_get_array_length获取 array 的 length
napi_is_array判断给定 napi_value 是否为 array
napi_set_element在数组指定索引处设置元素
napi_get_element获取数组指定索引处的元素
创建指定长度数组

如果需要创建指定长度的数组,可以使用 napi_create_array_with_length

#include "napi/native_api.h"

// napi_create_array_with_length
static napi_value CreateArrayWithLength(napi_env env, napi_callback_info info)
{
    // 获取ArkTS侧传入的参数
    size_t argc = 1;
    napi_value argv[1] = {nullptr};
    napi_value jsArray = nullptr;
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

    // 获取传递的数组长度
    int32_t length = 0;
    napi_get_value_int32(env, argv[0], &length);

    // 使用napi_create_array_with_length创建指定长度的数组
    napi_create_array_with_length(env, length, &jsArray);

    // 返回数组
    return jsArray;
}
分类常用函数
类型判断napi_typeofnapi_is_arraynapi_is_typedarray
创建值napi_create_doublenapi_create_string_utf8napi_create_objectnapi_create_array
获取值napi_get_value_doublenapi_get_value_string_utf8napi_get_value_bool
特殊值napi_get_undefinednapi_get_nullnapi_get_boolean
对象napi_get_named_propertynapi_set_named_property
数组napi_get_elementnapi_set_elementnapi_get_array_length
函数napi_create_functionnapi_call_functionnapi_get_cb_info
错误napi_throw_errornapi_throw_type_error
Promisenapi_create_promisenapi_resolve_promisenapi_reject_promise
引用napi_create_referencenapi_delete_reference