侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

NAPI 笔记 03:Value 和它派生的几个基本数据类型

barwe
2022-08-29 / 0 评论 / 3 点赞 / 2,466 阅读 / 5,017 字
温馨提示:
本文最后更新于 2023-06-07,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

NAPI 在 C++ 中用Napi::Value来表示 JavaScript 值,它对应 JavaScript 中的unknown类型。

Napi::Value的其他子类对应了 JavaScript 的响应类型:

  • Napi::Number
  • Napi::Boolean
  • Napi::String
  • Napi::Object
  • ...

Napi::Value类是对 Node-API 提供的napi_value的简单封装。

class Value

https://github.com/nodejs/node-addon-api/blob/main/doc/value.md

构造一个最基本的Value及其子类的实例需要指定一个Env对象和一个 C++ 原生值。

Value::Value();
Value::Value(napi_env env, napi_value value);

value 可以是各种原生类型,或者对原生类型的封装,例如bool, const char*, std::string, Napi::Value, napi_value等。

创建实例都必须指定一个env,即与之绑定的 JavaScript 运行环境,一般从待暴露的方法的参数中获取:

Number myfunc(const CallbackInfo& info) {
    Env env = info.Env();
    // 待暴露方法的返回值直接返回给了 JavaScript,所以需要和 Environment 绑定
    return Number::New(env, 1.0);
}

operators

// 返回底层 Node-API napi_type 类型的值,如果 Value 实例为空,返回 nullptr
Value::operator napi_value() const;
boolean Value::operator ==(const Value& other) const;
boolean Value::operator !=(const Value& other) const;

函数声明末尾加 const:该函数不能改变类的内部状态

  • 不能修改类的其他成员变量
  • 不能调用其他非 const 方法
  • 可以被其他 const 方法或者非 const 方法调用
  • 只能被 const 对象调用,即初始化对象时必须加 const:const Number n = Number(env, 0);

method As

将一个Value或其子类对象转换为指定类型的其他对象,这个转换不是强制的,当不能非常友好的进行转换时会报错。

template <typename T> T Value::As() const;

使用时需要通过泛型指定目标类型,例如:

Number n2 = n1.As<Number>();

将某个Value或者其子类的实例装换为Number类型。

method Env

返回实例关联的环境对象。

Env Value::Env() const;

methos IsXxx

类型实例是否是 JavaScript 中的某一种类型:

bool Value::IsBoolean() const;
bool Value::IsNumber() const;
bool Value::IsString() const;
bool Value::IsSymbol() const;
bool Value::IsObject() const;
bool Value::IsNull() const;
bool Value::IsUndefined() const;
bool Value::IsArray() const;
bool Value::ISBuffer() const;
bool Value::IsArrayBuffer() const;
bool Value::IsTypedArray() const;
bool Value::IsDataView() const;
bool Value::IsDate() const;
bool Value::IsFunction() const;
bool Value::IsPromise() const;

几个特殊的测试方法。

bool Value::StrictEquals(const Value& other) const;

与指定实例的底层值是否严格相等(类似于 JavaScript 的===)。

bool Value::IsEmpty() const;

实例是否被初始化:NAPI 允许创建未初始化的实例,这样的实例不能参与任何操作(无效),否则会引起异常。

需要注意的是,JavaScript 中的nullundefined是有效的值,用他们初始化的Value实例也是 有效 的。

当编译时禁用 C++ 异常处理,一个函数可能会返回一个未初始化的Value实例表示执行遇到了异常。

此时开发者需要在函数执行完成后手动检查Env::IsExceptionPending来判断函数执行是否发生异常。

bool Value::IsExternal() const;

实例的底层值是否是 Node-API 的外部对象。(没太深究啥意思)

method ToXxx

强制类型转换方法可能会引起异常,在禁用 C++ 异常时开发者应该手动检查Env::IsExceptionPending来测试函数是否正常调用。

Boolean Value::ToBoolean() const;
Number Value::ToNumber() const;
String Value::ToString() const;
Object Value::ToObject() const;

method Type

napi_valuetype Value::Type() const;

返回实例底层值的类型。

static method From

从 Node-API 原生值构建Value实例。

template <typename T>
static Value Value::From(napi_env env, const T& value);

上面的value就是 Node-API 中的原生值,它可以是:

  • C++ bool 类型,对应Napi::Boolean
  • C++ 整型和浮点数,对应Napi:Number
  • C++ 字符型常量指针const char*,需要 UTF-8 编码并且以 null 结尾,对应Napi::String
  • const char16_t*,UTF-16-LE 编码且以 null 结尾,对应Napi::String
  • std::string or std::u16string,对应Napi::String
  • Napi::Value or napi_value,对应Napi::Value

class Boolean

https://github.com/nodejs/node-addon-api/blob/main/doc/boolean.md

通过有参构造函数或者静态方法New来初始化一个实例:

Boolean(napi_env env, napi_value value);
Boolean Boolean::New(napi_env env, bool value);

其它 API:

bool Boolean::Value() const;
Boolean::operator bool() const;

class Number

https://github.com/nodejs/node-addon-api/blob/main/doc/number.md

对应 JavaScript 的Number对象,通过有参构造函数或者静态方法New来初始化一个实例:

Number(napi_env env, napi_value value);
Number Number::New(napi_env env, double value);

用于类型转换的实例方法:

int32_t Int32Value() const;
uint32_t Uint32Value() const;
int64_t Int64Value() const;
float FloatValue() const;
double DoubleValue() const;

转换为 C++ 中其他原生类型的 operator:

operator int32_t() const;
operator uint32_t() const;
operator int64_t() const;
operator float() const;
operator double() const;

class String

String类和Value类的继承关系是:Value => Name => String.

class Name

https://github.com/nodejs/node-addon-api/blob/main/doc/name.md

这个类用来描述 JavaScript 中的对象属性名称,它有两个子类:String & Symbol

一般应该直接使用String or Symbol

class String

https://github.com/nodejs/node-addon-api/blob/main/doc/string.md

对应 JavaScript 的String对象,通过有参构造函数或者静态方法New来初始化一个实例:

Napi::String::String(napi_env env, napi_value value);
Napi::String::New(napi_env env, const std::string& value);
Napi::String::New(napi_env env, const std::u16::string& value);
Napi::String::New(napi_env env, const char* value);
Napi::String::New(napi_env env, const char16_t* value);
Napi::String::New(napi_env env, const char* value, size_t length);
Napi::String::New(napi_env env, const char16_t* value, size_t length);

other API:

Napi::String::operator std::string() const;
Napi::String::operator std::u16string() const;

std::string Napi::String::Utf8Value() const;
std::u16string Napi::String::Utf16Value() const;

class Symbol

https://github.com/nodejs/node-addon-api/blob/main/doc/symbol.md

该类继承自Name类:Value => Name => Symbol.

初始化:

Napi::Symbol::New(napi_env env, const std::string& description);
Napi::Symbol::New(napi_env env, const char* description);
Napi::Symbol::New(napi_env env, Napi::String description);
Napi::Symbol::New(napi_env env, napi_value description);

static method WellKnown

不知道干啥的。

static method For

从已经存在的 symbol 中取回指定名称的 Symbol 对象,如果不存在则创建,它对应 JavaScript 中的Symbol.for()方法。

static Napi::Symbol Napi::Symbol::For(napi_env env, const std::string& description);
static Napi::Symbol Napi::Symbol::For(napi_env env, const char* description);
static Napi::Symbol Napi::Symbol::For(napi_env env, String description);
static Napi::Symbol Napi::Symbol::For(napi_env env, napi_value description);
3

评论区