使用JSVM-API接口操作bigint类型值
=======================

#### 简介

BigInt是JavaScript中用于表示任意精度整数的数据类型，能够处理比Number类型更大范围的整数值。JSVM-API提供的接口支持在JSVM模块中创建、获取和操作BigInt类型值。

#### 基本概念

使用JSVM-API接口操作BigInt类型值需要理解以下基本概念：

*   **BigInt类型：** BigInt是JavaScript中的一种数据类型，用于表示任意精度的整数。与Number类型不同，BigInt类型可以精确表示非常大的整数，而不会丢失精度或溢出。
*   **BigInt创建：** 使用JSVM-API提供的接口，可以通过传递C的int64或uint64数据来创建对应的JavaScript BigInt。这使得在JSVM模块中可以方便地创建BigInt类型值。
*   **BigInt操作：** JSVM-API提供了多个接口用于操作BigInt类型值。通过这些接口，可以获取BigInt的数值，进行数值转换，以及执行常见的算术和位运算操作。

#### 接口说明

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CreateBigintInt64 | 将C int64\_t类型的值转换为JavaScript BigInt类型。 |
| OH\_JSVM\_CreateBigintUint64 | 将C uint64\_t类型的值转换为JavaScript BigInt类型。 |
| OH\_JSVM\_CreateBigintWords | 将一组无符号64位字转换为单个BigInt值。 |
| OH\_JSVM\_GetValueBigintInt64 | 返回给定JavaScript BigInt的C int64\_t基础类型等价值。 如果需要，它将截断该值，将lossless设置为false。 |
| OH\_JSVM\_GetValueBigintUint64 | 返回给定JavaScript BigInt的C uint64\_t基础类型等价值。 如果需要，它将截断该值，将lossless设置为false。 |
| OH\_JSVM\_GetValueBigintWords | 将单个BigInt值转换为一个符号位、一个64位的小端数组和该数组的长度。 signBit和words参数可以都设置为NULL，这种情况下，只获取wordCount。 |

#### 使用示例

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

#### \[h2\]OH\_JSVM\_GetValueBigintWords

获取给定JavaScript BigInt对象的底层数据，即BigInt数据的字词表示。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
#include <fstream>

// OH\_JSVM\_GetValueBigintWords的样例方法
static JSVM\_Value GetValueBigintWords(JSVM\_Env env, JSVM\_CallbackInfo info) {
    size\_t argc = 1;
    JSVM\_Value args\[1\] = {nullptr};
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    int signBit = 0;
    size\_t wordCount = 0;
    uint64\_t\* words{nullptr};
    // 调用OH\_JSVM\_GetValueBigintWords接口获取wordCount
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, args\[0\], nullptr, &wordCount, nullptr);
    OH\_LOG\_INFO(LOG\_APP, "OH\_JSVM\_GetValueBigintWords wordCount:%{public}d.", wordCount);
    words = (uint64\_t\*)malloc(wordCount\*sizeof(uint64\_t));
    if (words == nullptr) {
        OH\_LOG\_ERROR(LOG\_APP, "OH\_JSVM\_GetValueBigintWords malloc failed.");
        return nullptr;
    }
    // 调用OH\_JSVM\_GetValueBigintWords接口获取传入bigInt相关信息，如：signBit传入bigInt正负信息
    status = OH\_JSVM\_GetValueBigintWords(env, args\[0\], &signBit, &wordCount, words);
    free(words);
    words = nullptr;
    if (status != JSVM\_OK) {
        OH\_LOG\_ERROR(LOG\_APP, "OH\_JSVM\_GetValueBigintWords fail, status:%{public}d.", status);
    } else {
        OH\_LOG\_INFO(LOG\_APP, "OH\_JSVM\_GetValueBigintWords signBit: %{public}d.", signBit);
    }
    // 将符号位转化为int类型传出去
    JSVM\_Value returnValue = nullptr;
    OH\_JSVM\_CreateInt32(env, signBit, &returnValue);
    return returnValue;
}
// GetValueBigintWords注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = GetValueBigintWords},
};
static JSVM\_CallbackStruct \*method = param;
// GetValueBigintWords方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"getValueBigintWords", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(getValueBigintWords(BigInt(5555555555555555)))JS";

预期的输出结果

OH\_JSVM\_GetValueBigintWords wordCount:1.
OH\_JSVM\_GetValueBigintWords signBit: 0.

#### \[h2\]OH\_JSVM\_CreateBigintWords

根据给定的uint64\_t数组创建一个JavaScript BigInt对象。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
// OH\_JSVM\_CreateBigintWords的样例方法
static int DIFF\_VALUE\_THREE = 3;
static JSVM\_Value CreateBigintWords(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    // 使用OH\_JSVM\_CreateBigintWords接口创建一个BigInt对象
    int signBit = 0;
    size\_t wordCount = DIFF\_VALUE\_THREE;
    uint64\_t words\[\] = {12ULL, 34ULL, 56ULL};
    JSVM\_Value returnValue = nullptr;
    JSVM\_Status status = OH\_JSVM\_CreateBigintWords(env, signBit, wordCount, words, &returnValue);
    if (status != JSVM\_OK) {
        OH\_LOG\_ERROR(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintWords fail");
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintWords success");
    }
    return returnValue;
}
// CreateBigintWords注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = CreateBigintWords},
};
static JSVM\_CallbackStruct \*method = param;
// CreateBigintWords方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"createBigintWords", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(createBigintWords())JS";

预期的输出结果

JSVM OH\_JSVM\_CreateBigintWords success

#### \[h2\]OH\_JSVM\_CreateBigintUint64

根据给定的uint64类型对象创建JavaScript BigInt对象。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
// 声明uint64\_t的变量value
static uint64\_t TEST\_VALUE = 5555555555555555555;
// OH\_JSVM\_CreateBigintUint64的样例方法
static JSVM\_Value CreateBigintUint64(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    // 将value转化为JSVM\_Value类型返回
    JSVM\_Value returnValue = nullptr;
    JSVM\_Status status = OH\_JSVM\_CreateBigintUint64(env, TEST\_VALUE, &returnValue);
    if (status != JSVM\_OK) {
        OH\_LOG\_ERROR(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintUint64 fail");
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintUint64 success");
    }
    return returnValue;
}
// CreateBigintUint64注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = CreateBigintUint64},
};
static JSVM\_CallbackStruct \*method = param;
// CreateBigintUint64方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"createBigintUint64", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(createBigintUint64())JS";

预期的输出结果

JSVM OH\_JSVM\_CreateBigintUint64 success

#### \[h2\]OH\_JSVM\_GetValueBigintUint64

获取给定JavaScript BigInt的uint64\_t基础类型值。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
// OH\_JSVM\_GetValueBigintUint64的样例方法
static JSVM\_Value GetValueBigintUint64(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    size\_t argc = 1;
    JSVM\_Value args\[1\] = {nullptr};
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    // 从参数值中获取BigInt的数值
    uint64\_t value = 0;
    bool lossLess = false;
    OH\_JSVM\_GetValueBigintUint64(env, args\[0\], &value, &lossLess);
    // 判断从JS侧获取bigint是否为无损转换，如果不是抛出异常
    if (!lossLess) {
        OH\_JSVM\_ThrowError(env, nullptr, "BigInt values have no lossless conversion");
        return nullptr;
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM GetValueBigintUint64 success");
    }
    JSVM\_Value returnValue = nullptr;
    OH\_JSVM\_CreateBigintUint64(env, value, &returnValue);
    return returnValue;
}
// GetValueBigintUint64注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = GetValueBigintUint64},
};
static JSVM\_CallbackStruct \*method = param;
// GetValueBigintUint64方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"getValueBigintUint64", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(getValueBigintUint64(BigInt(5555555555555555)))JS";

预期的输出结果

JSVM GetValueBigintUint64 success

#### \[h2\]OH\_JSVM\_CreateBigintInt64

根据给定的uint64类型对象创建JavaScript BigInt对象。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
// 声明int64\_t的变量value
static int64\_t TEST\_VALUE\_DEMO = -5555555555555555555;
// OH\_JSVM\_CreateBigintInt64的样例方法
static JSVM\_Value CreateBigintInt64(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    JSVM\_Value returnValue = nullptr;
    JSVM\_Status status = OH\_JSVM\_CreateBigintInt64(env, TEST\_VALUE\_DEMO, &returnValue);
    if (status != JSVM\_OK) {
        OH\_LOG\_ERROR(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintInt64 fail");
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM OH\_JSVM\_CreateBigintInt64 success");
    }
    return returnValue;
}
// CreateBigintInt64注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = CreateBigintInt64},
};
static JSVM\_CallbackStruct \*method = param;
// CreateBigintInt64方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"createBigintInt64", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(createBigintInt64())JS";

预期的输出结果

JSVM OH\_JSVM\_CreateBigintInt64 success

#### \[h2\]OH\_JSVM\_GetValueBigintInt64

用于从传入的参数中提取64位整数的BigInt数据，以供后续处理。

cpp部分代码：

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>
// OH\_JSVM\_GetValueBigintInt64的样例方法
static JSVM\_Value GetBigintInt64(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    size\_t argc = 1;
    JSVM\_Value args\[1\] = {nullptr};
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    // 从传入的参数中提取64位整数的BigInt数据
    int64\_t value = 0;
    bool lossLess = false;
    OH\_JSVM\_GetValueBigintInt64(env, args\[0\], &value, &lossLess);
    // 判断从JS侧获取bigint是否为无损转换，如果不是抛出异常
    if (!lossLess) {
        OH\_JSVM\_ThrowError(env, nullptr, "BigInt values have no lossless conversion");
        return nullptr;
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM GetBigintInt64 success");
    }
    JSVM\_Value returnValue = nullptr;
    OH\_JSVM\_CreateBigintInt64(env, value, &returnValue);
    return returnValue;
}
// GetBigintInt64注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = GetBigintInt64},
};
static JSVM\_CallbackStruct \*method = param;
// GetBigintInt64方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"getBigintInt64", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};
// 样例测试js
const char\* srcCallNative = R"JS(getBigintInt64(BigInt(-5555555555555555)))JS";

预期的输出结果

JSVM GetValueBigintUint64 success