使用Node-API接口创建基本数据类型
====================

#### 简介

ArkTS的Number类型是一个双精度64位二进制格式IEEE 754值。只有在-2^53+1到2^53-1范围内（闭区间）的整数才能在不丢失精度的情况下被表示，在超过该取值范围的情况下，需要使用BigInt对应的Node-API接口来处理更大范围的整数。

#### 基本概念

当使用Node-API接口进行数值类型的创建和获取时，有一些基本概念需要了解：

*   **数值类型**：在使用Node-API接口时，可能需要从Node-API模块数值类型转换为ArkTS数值类型值，或者从ArkTS数据类型值转换为Node-API模块数值类型。在进行数据类型转换时，需要注意数据范围是否匹配，以及有无符号整数和双精度数值等区别。
*   **错误处理**：在使用这些接口时，需要对可能发生的错误进行适当处理。比如，在创建整数值时可能发生内存分配错误或其他运行时错误，需要使用Node-API提供的错误处理机制来捕获并处理这些错误。
*   **ArkTS交互**：在开发过程中，需要考虑如何将创建的数值类型值与ArkTS环境进行交互，包括传递参数、返回值等。

#### 场景和功能介绍

以下Node-API函数通常在开发ArkTS的Node-API模块时使用，以便处理数值类型值，帮助开发人员在Node-API模块中和ArkTS数值进行交互：

| 接口 | 描述 |
| :-- | :-- |
| [napi\_get\_value\_uint32](#napi_get_value_uint32) | 将从ArkTS环境中获取的number类型数据转为Node-API模块中的uint32\_t类型数据。 |
| [napi\_get\_value\_int32](#napi_get_value_int32) | 将从ArkTS环境中获取的number类型数据转为Node-API模块中的int32\_t类型数据。 |
| [napi\_get\_value\_int64](#napi_get_value_int64) | 将从ArkTS环境中获取的number类型数据转为Node-API模块中的int64\_t类型数据。 |
| [napi\_get\_value\_double](#napi_get_value_double) | 将从ArkTS环境中获取的number类型数据转为Node-API模块中的double类型数据。 |
| [napi\_get\_value\_bool](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-primitive#napi_get_value_bool) | 将ArkTS环境中获取的boolean类型数据转为Node-API模块中的bool类型数据。 |
| [napi\_get\_value\_string\_utf8](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_get_value_string_utf8) | 将ArkTS环境中获取的string类型数据转为Node-API模块中的utf8编码的字符类型数据。 |
| [napi\_get\_value\_string\_utf16](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_get_value_string_utf16) | 将ArkTS环境中获取的string类型数据转为Node-API模块中的utf16编码的字符类型数据。 |
| [napi\_get\_value\_string\_latin1](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_get_value_string_latin1) | 将ArkTS环境中获取的string类型数据转为Node-API模块中的ISO-8859-1编码的字符类型数据。 |
| [napi\_create\_int32](#napi_create_int32) | 将Node-API模块中的int32\_t类型转换为ArkTS环境中number类型。 |
| [napi\_create\_uint32](#napi_create_uint32) | 将Node-API模块中的uint32\_t类型转换为ArkTS环境中number类型。 |
| [napi\_create\_int64](#napi_create_int64) | 将Node-API模块中的int64\_t类型转换为ArkTS环境中number类型。 |
| [napi\_create\_double](#napi_create_double) | 将Node-API模块中的double类型转换为ArkTS环境中number类型。 |
| [napi\_get\_boolean](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-primitive#napi_get_boolean) | 将Node-API模块中的bool类型转换为ArkTS环境中boolean类型。 |
| [napi\_create\_string\_utf8](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_create_string_utf8) | 将Node-API模块中的utf8编码的字符串类型转换为ArkTS环境中string类型。 |
| [napi\_create\_string\_utf16](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_create_string_utf16) | 将Node-API模块中的utf16编码的字符串类型转换为ArkTS环境中string类型。 |
| [napi\_create\_string\_latin1](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_create_string_latin1) | 将Node-API模块中的ISO-8859-1编码的字符串类型转换为ArkTS环境中string类型。 |
| [napi\_create\_external\_string\_ascii](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_create_external_string_ascii) | 将Node-API模块中的ascii编码的字符串类型无拷贝的转换为ArkTS环境中string类型。 |
| [napi\_create\_external\_string\_utf16](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-about-string#napi_create_external_string_utf16) | 将Node-API模块中的utf16编码的字符串类型无拷贝的转换为ArkTS环境中string类型。 |

#### 使用示例

Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-process)，本文仅对接口对应C++及ArkTS相关代码进行展示。

#### \[h2\]napi\_get\_value\_uint32

用于从ArkTS环境中获取32位无符号整数值。

cpp部分代码

// napi\_get\_value\_uint32
static napi\_value GetValueUint32(napi\_env env, napi\_callback\_info info)
{
    // 获取传入的数字类型参数
    size\_t argc = 1;
    napi\_value argv\[1\] = {nullptr};
    // 解析传入的参数
    napi\_get\_cb\_info(env, info, &argc, argv, nullptr, nullptr);

    uint32\_t number = 0;
    // 获取传入参数的值中的无符号32位整数
    napi\_status status = napi\_get\_value\_uint32(env, argv\[0\], &number);
    // 如果传递的参数不是数字,将会返回napi\_number\_expected，设置函数返回nullptr
    if (status != napi\_ok) {
        return nullptr;
    }
    napi\_value result = nullptr;
    // 创建传入参数无符号32位整数，并传出
    napi\_create\_uint32(env, number, &result);
    return result;
}

接口声明

export const getValueUint32: <T>(data: T) => number | undefined; // napi\_get\_value\_uint32

ArkTS侧示例代码

// napi\_get\_value\_uint32
let value = testNapi.getValueUint32<number>(111111111111);
let data = testNapi.getValueUint32<string>("sssss");
hilog.info(0x0000, 'Node-API', 'get\_value\_uint32\_number %{public}d', value);
// 传入非数字"sssss"时函数返回undefined
hilog.info(0x0000, 'Node-API', 'get\_value\_uint32\_number %{public}s', data);
// 传入uint32范围内的数字100时函数返回原数字
hilog.info(0x0000, 'Node-API', 'get\_value\_uint32\_number %{public}d',
  testNapi.getValueUint32<number>(100));

#### \[h2\]napi\_get\_value\_int32

将ArkTS value转为Node-API模块中的int32类型数据。

cpp部分代码

// napi\_get\_value\_int32
static napi\_value GetValueInt32(napi\_env env, napi\_callback\_info info)
{
    size\_t argc = 1;
    napi\_value args\[1\] = {nullptr};
    int32\_t result32 = 0;
    // 解析传递的参数
    napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    // 将前端传过来的参数转为Node-API模块的int32类型
    napi\_status status = napi\_get\_value\_int32(env, args\[0\], &result32);
    // 如果传递的参数不是数字napi\_get\_value\_int32接口将会返回napi\_number\_expected，设置函数返回nullptr
    if (status != napi\_ok) {
        return nullptr;
    }
    // 调用napi\_create\_int32接口将int32类型的数据转为napi\_value返回
    napi\_value napiResult32 = nullptr;
    napi\_create\_int32(env, result32, &napiResult32);
    return napiResult32;
}

接口声明

export const getValueInt32: (value: number | string) => number | undefined; // napi\_get\_value\_int32

ArkTS侧示例代码

// napi\_get\_value\_int32
// 传入非数字“ss”时函数返回undefined
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_not\_number %{public}s', testNapi.getValueInt32('ss'));
// 传入int32范围内的数字100时函数返回原数字
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_number %{public}d', testNapi.getValueInt32(100));
// 传入68719476735，此数字的二进制为111111111111111111111111111111111111，在int32类型中此二进制代表数字-1
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_oversize %{public}d',
  testNapi.getValueInt32(68719476735));
// 大于2的31次-1的数字且不是二进制为111111111111111111111111111111111111这样的在int32中有特殊含义的数字也会溢出，导致数值发生改变，返回值按后32位二进制编码解码
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_oversize %{public}d',
  testNapi.getValueInt32(687194767355));
// 传入NAN（not a number）、+Infinity（正无穷）或-Infinity（负无穷），会返回数字0
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_number\_NAN %{public}d', testNapi.getValueInt32(NaN));
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_number\_+Infinity %{public}d',
  testNapi.getValueInt32(+Infinity));
hilog.info(0x0000, 'Node-API', 'get\_value\_int32\_number\_-Infinity %{public}d',
  testNapi.getValueInt32(-Infinity));

#### \[h2\]napi\_get\_value\_int64

将ArkTS value转为Node-API模块中的int64类型数据。

cpp部分代码

// napi\_get\_value\_int64
static napi\_value GetValueInt64(napi\_env env, napi\_callback\_info info)
{
    size\_t argc = 1;
    napi\_value args\[1\] = {nullptr};
    int64\_t result64 = 0;
    // 解析传递的值
    napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    // 将前端传过来的参数转为Node-API模块的int64类型
    napi\_status status = napi\_get\_value\_int64(env, args\[0\], &result64);
    // 如果传递的参数不是数字, 返回napi\_number\_expected.
    if (status != napi\_ok) {
        return nullptr;
    }
    // 调用napi\_create\_int64接口将int64类型的数据转为napi\_value返回前端
    napi\_value napiResult64 = nullptr;
    napi\_create\_int64(env, result64, &napiResult64);
    return napiResult64;
}

接口声明

export const getValueInt64: (value: number | string) => number | undefined; // napi\_get\_value\_int64

ArkTS侧示例代码

// napi\_get\_value\_int64
// 输入不超过int64表示范围的数字，会返回该数字
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_number %{public}d', testNapi.getValueInt64(80));
// 传入非数字“ss”，获得函数返回的值应为undefined
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_not\_number %{public}s',
  testNapi.getValueInt64('sAs'));
// 输入超过int64表示范围的数字会溢出，失去精度，导致输入数字与返回数字不相等
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_number\_oversize %{public}d',
  testNapi.getValueInt64(9223372036854775809));
// 传入NAN（not a number）、+Infinity（正无穷）或-Infinity（负无穷）接口返回数字0
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_number\_NAN %{public}d', testNapi.getValueInt64(NaN));
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_number\_+Infinity %{public}d',
  testNapi.getValueInt64(+Infinity));
hilog.info(0x0000, 'Node-API', 'get\_value\_int64\_number\_-Infinity %{public}d',
  testNapi.getValueInt64(-Infinity));

#### \[h2\]napi\_get\_value\_double

将ArkTS value转为Node-API模块中的double类型数据。

cpp部分代码

// napi\_get\_value\_double
static napi\_value GetDouble(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;
    napi\_status status = napi\_get\_value\_double(env, args\[0\], &value);
    // 传入非数字接口返回napi\_number\_expected
    if (status != napi\_ok) {
        return nullptr;
    }
    napi\_value result = nullptr;
    napi\_create\_double(env, value, &result);
    return result;
}

接口声明

export const getDouble: (value: number | string) => number | undefined; // napi\_get\_value\_double

ArkTS侧示例代码

// napi\_get\_value\_double
// 输入数字，返回该数字
hilog.info(0x0000, 'Node-API', 'get\_value\_double\_number %{public}d', testNapi.getDouble(80.885));
// 传入非数字，获得函数返回的值应为undefined
hilog.info(0x0000, 'Node-API', 'get\_value\_double\_not\_number %{public}s', testNapi.getDouble('sAs'));

#### \[h2\]napi\_create\_int32

用于创建一个ArkTS数字（int32类型）的值。

cpp部分代码

// napi\_create\_int32
static napi\_value CreateInt32(napi\_env env, napi\_callback\_info info)
{
    // int32\_t是有符号的32位整数类型，表示带有符号的整数，它的范围是从-2^31到2^31 - 1，也就是-2147483648到2147483647
    // 要表示的整数值
    int32\_t value = -26;
    // 创建ArkTS中的int32数字
    napi\_value result = nullptr;
    napi\_status status = napi\_create\_int32(env, value, &result);
    if (status != napi\_ok) {
        // 处理错误
        napi\_throw\_error(env, nullptr, "Failed to create int32 value");
    }
    return result;
}

接口声明

export const createInt32: () => number; // napi\_create\_int32

ArkTS侧示例代码

// napi\_create\_int32
hilog.info(0x0000, 'testTag', 'Test Node-API napi\_create\_int32：' + testNapi.createInt32());

#### \[h2\]napi\_create\_uint32

用于创建一个ArkTS数字（uint32类型）的值。

cpp部分代码

// napi\_create\_uint32
static napi\_value CreateUInt32(napi\_env env, napi\_callback\_info info)
{
    // 如果使用
    // uint32\_t类型来定义-26，会发生溢出，溢出时会对结果进行模运算，将负数的二进制补码转换为相应的正数。-26输出4294967270
    // uint32\_t是无符号的32位整数类型，只能表示非负整数。它的范围是从0到2 ^32 - 1，即0到4294967295
    // 要表示的整数值
    uint32\_t value = 26;
    // 创建ArkTS中的uint32数字
    napi\_value result = nullptr;
    napi\_status status = napi\_create\_uint32(env, value, &result);
    if (status != napi\_ok) {
        // 处理错误
        napi\_throw\_error(env, nullptr, "Failed to create uint32 value");
    }
    return result;
}

接口声明

export const createUInt32: () => number; // napi\_create\_uint32

ArkTS侧示例代码

// napi\_create\_uint32
hilog.info(0x0000, 'testTag', 'Test Node-API napi\_create\_uint32: ' + testNapi.createUInt32());

#### \[h2\]napi\_create\_int64

用于创建一个ArkTS数字（int64类型）的值。

cpp部分代码

// napi\_create\_int64
static napi\_value CreateInt64(napi\_env env, napi\_callback\_info info)
{
    // int64是有符号的64位整数类型，可以表示范围从-2^63到2^63 - 1的整数，即 -9223372036854775808到9223372036854775807
    // 要表示的整数值
    int64\_t value = 2147483648;
    // 使用给定数值创建一个ArkTS number，仅能准确表示范围从-2^53 + 1到2^53 - 1（闭区间）的整数
    // 如果想表示的数值超过了2^53，请使用napi\_create\_bigint64接口
    napi\_value result = nullptr;
    napi\_status status = napi\_create\_int64(env, value, &result);
    if (status != napi\_ok) {
        // 处理错误
        napi\_throw\_error(env, nullptr, "Failed to create int64 value");
    }
    return result;
}

接口声明

export const createInt64: () => number; // napi\_create\_int64

ArkTS侧示例代码

// napi\_create\_int64
hilog.info(0x0000, 'testTag', 'Test Node-API napi\_create\_int64: ' + testNapi.createInt64());

#### \[h2\]napi\_create\_double

用于创建一个ArkTS数字（double类型）的值。

cpp部分代码

// napi\_create\_double
static napi\_value CreateDouble(napi\_env env, napi\_callback\_info info)
{
    double value = 1.234;
    // 创建ArkTS中的double数字
    napi\_value result = nullptr;
    napi\_status status = napi\_create\_double(env, value, &result);
    if (status != napi\_ok) {
        // 处理错误
        napi\_throw\_error(env, nullptr, "Failed to create double value");
    }
    return result;
}

接口声明

export const createDouble: () => number; // napi\_create\_double

ArkTS侧示例代码

// napi\_create\_double
hilog.info(0x0000, 'testTag', 'Test Node-API napi\_create\_double: ' + testNapi.createDouble());

以上代码如果要在native cpp中打印日志，需在CMakeLists.txt文件中添加以下配置信息（并添加头文件：#include "hilog/log.h"）：

// CMakeLists.txt
add\_definitions( "-DLOG\_DOMAIN=0xd0d0" )
add\_definitions( "-DLOG\_TAG=\\"testTag\\"" )
target\_link\_libraries(entry PUBLIC libace\_napi.z.so libhilog\_ndk.z.so)