目录

Creating Basic Data Types Using Node-API

Introduction

The ArkTS Number type represents a double-precision 64-bit binary IEEE 754 value. Only integers in the range of -2^53+1 to 2^53-1 (inclusive) can be represented without loss of precision. Integers out of this range must be handled by Node-API interfaces for BigInt.

Basic Concepts

Before using Node-API to create and obtain numbers, you need to understand the following concepts:

Available APIs

The following table lists the APIs provided by the Node-API module for converting number types between ArkTS and C/C++.

API Description
napi_get_value_uint32 Obtains a C uint32_t value from an ArkTS number.
napi_get_value_int32 Obtains a C int32_t value from an ArkTS number.
napi_get_value_int64 Obtains a C int64_t value from an ArkTS number.
napi_get_value_double Obtains a C double value from an ArkTS number.
napi_get_value_bool Obtains a C bool value from an ArkTS boolean.
napi_get_value_string_utf8 Obtains a C UTF-8-encoded string value from an ArkTS string.
napi_get_value_string_utf16 Obtains a C UTF-16-encoded string value from an ArkTS string.
napi_get_value_string_latin1 Obtains a C ISO-8859-1-encoded string value from an ArkTS string.
napi_create_int32 Creates an ArkTS number from a 32-bit signed integer.
napi_create_uint32 Creates an ArkTS number from a 32-bit unsigned integer.
napi_create_int64 Creates an ArkTS number from a 64-bit signed integer.
napi_create_double Creates an ArkTS number from a double-precision floating-point number.
napi_get_boolean Obtains an ArkTS boolean from a C bool.
napi_create_string_utf8 Creates an ArkTS string from a C UTF-8-encoded string.
napi_create_string_utf16 Creates an ArkTS string from a C UTF-16-encoded string.
napi_create_string_latin1 Creates an ArkTS string from a C ISO-8859-1-encoded string.
napi_create_external_string_ascii Creates an ArkTS string from a C ASCII-encoded string without copying.
napi_create_external_string_utf16 Creates an ArkTS string from a C UTF16-encoded string without copying.

Example

If you are just starting out with Node-API, see Node-API Development Process. The following demonstrates only the C++ and ArkTS code involved in the APIs for manipulating basic data types.

[h2]napi_get_value_uint32

Use napi_get_value_uint32 to obtain a 32-bit unsigned integer from an ArkTS number.

CPP code:

// napi_get_value_uint32
static napi_value GetValueUint32(napi_env env, napi_callback_info info)
{
    // Obtain the numeric type parameter passed in.
    size_t argc = 1;
    napi_value argv[1] = {nullptr};
    // Parse the passed-in parameter.
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

    uint32_t number = 0;
    // Obtain the unsigned 32-bit integer from the passed-in parameter value.
    napi_status status = napi_get_value_uint32(env, argv[0], &number);
    // If the passed-in parameter is not a number, napi_number_expected is returned and the function returns nullptr.
    if (status != napi_ok) {
        return nullptr;
    }
    napi_value result = nullptr;
    // Create an unsigned 32-bit integer from the passed-in parameter and return it.
    napi_create_uint32(env, number, &result);
    return result;
}

API declaration:

export const getValueUint32: <T>(data: T) => number | undefined; // napi_get_value_uint32

ArkTS code:

// 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);
// When a non-number "sssss" is passed in, the function returns undefined.
hilog.info(0x0000, 'Node-API', 'get_value_uint32_number %{public}s', data);
// When the number 100 within the uint32 range is passed in, the function returns the original number.
hilog.info(0x0000, 'Node-API', 'get_value_uint32_number %{public}d',
  testNapi.getValueUint32<number>(100));

[h2]napi_get_value_int32

Use napi_get_value_int32 to convert an ArkTS value to a C int32 value.

CPP code:

// 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;
    // Parse the passed-in parameter.
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // Convert the parameter passed from the frontend to the int32 type of the Node-API module.
    napi_status status = napi_get_value_int32(env, args[0], &result32);
    // If the passed-in parameter is not a number, the napi_get_value_int32 API returns napi_number_expected and the function returns nullptr.
    if (status != napi_ok) {
        return nullptr;
    }
    // Call the napi_create_int32 API to convert int32 data to napi_value and return it.
    napi_value napiResult32 = nullptr;
    napi_create_int32(env, result32, &napiResult32);
    return napiResult32;
}

API declaration:

export const getValueInt32: (value: number | string) => number | undefined; // napi_get_value_int32

ArkTS code:

// napi_get_value_int32
// When a non-number "ss" is passed in, the function returns undefined.
hilog.info(0x0000, 'Node-API', 'get_value_int32_not_number %{public}s', testNapi.getValueInt32('ss'));
// When the number 100 within the int32 range is passed in, the function returns the original number.
hilog.info(0x0000, 'Node-API', 'get_value_int32_number %{public}d', testNapi.getValueInt32(100));
// When 68719476735 is passed in, its binary representation is 111111111111111111111111111111111111, which represents -1 in the int32 type.
hilog.info(0x0000, 'Node-API', 'get_value_int32_oversize %{public}d',
  testNapi.getValueInt32(68719476735));
// Numbers greater than 2^31 - 1 that do not have a binary representation like 111111111111111111111111111111111111 (which has special meaning in int32) also overflow, causing the value to change. The return value is decoded based on the last 32 bits of the binary encoding.
hilog.info(0x0000, 'Node-API', 'get_value_int32_oversize %{public}d',
  testNapi.getValueInt32(687194767355));
// Passing NaN (not a number), +Infinity (positive infinity), or -Infinity (negative infinity) returns the number 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

Use napi_get_value_int64 to convert an ArkTS value to a C int64 value.

CPP code:

// 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;
    // Parse the passed-in value.
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // Convert the parameter passed from the frontend to the int64 type of the Node-API module.
    napi_status status = napi_get_value_int64(env, args[0], &result64);
    // If the passed-in parameter is not a number, napi_number_expected is returned.
    if (status != napi_ok) {
        return nullptr;
    }
    // Call the napi_create_int64 API to convert int64 data to napi_value and return it to the frontend.
    napi_value napiResult64 = nullptr;
    napi_create_int64(env, result64, &napiResult64);
    return napiResult64;
}

API declaration:

export const getValueInt64: (value: number | string) => number | undefined; // napi_get_value_int64

ArkTS code:

// napi_get_value_int64
// When a number within the int64 representable range is passed in, that number is returned.
hilog.info(0x0000, 'Node-API', 'get_value_int64_number %{public}d', testNapi.getValueInt64(80));
// When a non-number "ss" is passed in, the value returned by the function should be undefined.
hilog.info(0x0000, 'Node-API', 'get_value_int64_not_number %{public}s',
  testNapi.getValueInt64('sAs'));
// When a number exceeding the int64 representable range is passed in, it overflows and loses precision, causing the input number and the returned number to differ.
hilog.info(0x0000, 'Node-API', 'get_value_int64_number_oversize %{public}d',
  testNapi.getValueInt64(9223372036854775809));
// When NaN (not a number), +Infinity (positive infinity), or -Infinity (negative infinity) is passed, the API returns 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

Use napi_get_value_double to convert an ArkTS value to a C double value.

CPP code:

// 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);
    // When a non-number is passed in, the API returns napi_number_expected.
    if (status != napi_ok) {
        return nullptr;
    }
    napi_value result = nullptr;
    napi_create_double(env, value, &result);
    return result;
}

API declaration:

export const getDouble: (value: number | string) => number | undefined; // napi_get_value_double

ArkTS code:

// napi_get_value_double
// When a number is passed in, that number is returned.
hilog.info(0x0000, 'Node-API', 'get_value_double_number %{public}d', testNapi.getDouble(80.885));
// When a non-number is passed in, the value returned by the function should be undefined.
hilog.info(0x0000, 'Node-API', 'get_value_double_not_number %{public}s', testNapi.getDouble('sAs'));

[h2]napi_create_int32

Use napi_create_int32 to create an ArkTS number from a 32-bit signed integer.

CPP code:

// napi_create_int32
static napi_value CreateInt32(napi_env env, napi_callback_info info)
{
    // int32_t is a signed 32-bit integer type that represents signed integers. Its range is from -2^31 to 2^31 - 1, that is, from -2147483648 to 2147483647.
    // The integer value to represent.
    int32_t value = -26;
    // Create an int32 number in ArkTS.
    napi_value result = nullptr;
    napi_status status = napi_create_int32(env, value, &result);
    if (status != napi_ok) {
        // Handle the error.
        napi_throw_error(env, nullptr, "Failed to create int32 value");
    }
    return result;
}

API declaration:

export const createInt32: () => number; // napi_create_int32

ArkTS code:

// napi_create_int32
hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_int32:' + testNapi.createInt32());

[h2]napi_create_uint32

Use napi_create_uint32 to create an ArkTS number from a 32-bit unsigned integer.

CPP code:

// napi_create_uint32
static napi_value CreateUInt32(napi_env env, napi_callback_info info)
{
    // If you use
    // the uint32_t type to define -26, an overflow occurs. When overflow happens, a modulo operation is performed on the result, converting the two's complement of the negative number to the corresponding positive number. -26 outputs 4294967270.
    // uint32_t is an unsigned 32-bit integer type that can only represent non-negative integers. Its range is from 0 to 2^32 - 1, that is, from 0 to 4294967295.
    // The integer value to represent.
    uint32_t value = 26;
    // Create a uint32 number in ArkTS.
    napi_value result = nullptr;
    napi_status status = napi_create_uint32(env, value, &result);
    if (status != napi_ok) {
        // Handle the error.
        napi_throw_error(env, nullptr, "Failed to create uint32 value");
    }
    return result;
}

API declaration:

export const createUInt32: () => number; // napi_create_uint32

ArkTS code:

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

[h2]napi_create_int64

Use napi_create_int64 to create an ArkTS number from a 64-bit signed integer.

CPP code:

// napi_create_int64
static napi_value CreateInt64(napi_env env, napi_callback_info info)
{
    // int64 is a signed 64-bit integer type that can represent integers ranging from -2^63 to 2^63 - 1, that is, from -9223372036854775808 to 9223372036854775807.
    // The integer value to represent.
    int64_t value = 2147483648;
    // Create an ArkTS number using the given value. Only integers in the range from -2^53 + 1 to 2^53 - 1 (inclusive) can be accurately represented.
    // If the value to represent exceeds 2^53, use the napi_create_bigint_int64 API.
    napi_value result = nullptr;
    napi_status status = napi_create_int64(env, value, &result);
    if (status != napi_ok) {
        // Handle the error.
        napi_throw_error(env, nullptr, "Failed to create int64 value");
    }
    return result;
}

API declaration:

export const createInt64: () => number; // napi_create_int64

ArkTS code:

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

[h2]napi_create_double

Use napi_create_double to create an ArkTS number from a double-precision floating-point number.

CPP code:

// napi_create_double
static napi_value CreateDouble(napi_env env, napi_callback_info info)
{
    double value = 1.234;
    // Create a double number in ArkTS.
    napi_value result = nullptr;
    napi_status status = napi_create_double(env, value, &result);
    if (status != napi_ok) {
        // Handle the error.
        napi_throw_error(env, nullptr, "Failed to create double value");
    }
    return result;
}

API declaration:

export const createDouble: () => number; // napi_create_double

ArkTS code:

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

To print logs in the native CPP, add the following information to the CMakeLists.txt file and add the header file by using #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)