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 中的null
和undefined
是有效的值,用他们初始化的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
orstd::u16string
,对应Napi::String
Napi::Value
ornapi_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);
评论区