Add-on Structure

插件结构

Napi::Addon<T>类继承自Napi::InstanceWrap<T>类。

创建能在从同一源包多次加载到多个 Node.js 线程和 / 或多次加载到同一 Node.js 线程时正常工作的插件,要求它们所持有的所有全局数据都必须与运行它们的环境相关联。将全局数据存储在静态变量中是不安全的,因为这样做没有考虑到插件可能被加载到多个线程中,也没有考虑到插件可能在单个线程中被多次加载。

Napi::Addon<T>类可用于定义整个插件。Napi::Addon<T>子类的实例成为插件的实例,由 Node.js 安全地存储在其各个线程和各个上下文中。因此,存储在Napi::Addon<T>子类实例的实例变量中的任何数据都会被 Node.js 安全存储。使用Napi::Addon<T>::InstanceMethod和 / 或Napi::Addon<T>::DefineAddon向 JavaScript 暴露的函数是Napi::Addon子类的实例方法,因此可以访问存储在实例内部的数据。

Napi::Addon<T>::DefineProperties可用于将Napi::Addon<T>子类实例方法附加到除了将返回给 Node.js 作为插件实例的对象之外的其他对象上。

Napi::Addon<T>类可以与NODE_API_ADDON()NODE_API_NAMED_ADDON()宏一起使用来定义插件。

示例

cpp 复制代码
#include <napi.h>

class ExampleAddon : public Napi::Addon<ExampleAddon> {
 public:
  ExampleAddon(Napi::Env env, Napi::Object exports) {
    // 在构造函数中,我们声明插件向JavaScript提供的函数
    DefineAddon(exports, {
      InstanceMethod("increment", &ExampleAddon::Increment),

      // 我们还可以将普通对象附加到`exports`,并将实例方法作为这些子对象的属性
      InstanceValue("subObject", DefineProperties(Napi::Object::New(env), {
        InstanceMethod("decrement", &ExampleAddon::Decrement)
      }), napi_enumerable)
    });
  }
 private:

  // 此方法可以访问存储在环境中的数据,因为它是`ExampleAddon`的实例方法,并且在构造函数中被列入传递给`DefineAddon()`的属性描述符中
  Napi::Value Increment(const Napi::CallbackInfo& info) {
    return Napi::Number::New(info.Env(), ++value);
  }

  // 此方法可以访问存储在环境中的数据,因为它是`ExampleAddon`的实例方法,并且通过调用`DefineProperties()`将其暴露给JavaScript,附加到对应的对象上
  Napi::Value Decrement(const Napi::CallbackInfo& info) {
    return Napi::Number::New(info.Env(), --value);
  }

  // 存储在这些变量中的数据对于插件的每个实例都是唯一的
  uint32_t value = 42;
};

// 该宏声明,对于必须加载到Node.js中的每个插件实例,都会创建`ExampleAddon`类的实例
NODE_API_ADDON(ExampleAddon)

上述代码可在 JavaScript 中按如下方式使用:

javascript 复制代码
'use strict'

const exampleAddon = require('bindings')('example_addon');
console.log(exampleAddon.increment()); // 输出 43
console.log(exampleAddon.increment()); // 输出 44
console.log(exampleAddon.subObject.decrement()); // 输出 43

当 Node.js 加载插件的一个实例时,会创建该类的一个新实例。其构造函数接收环境Napi::Env env和导出对象Napi::Object exports。然后,它可以使用DefineAddon方法要么将方法、访问器和 / 或值附加到exports对象,要么创建自己的exports对象并将方法、访问器和 / 或值附加到该对象上。

注意Napi::Addon<T>在内部使用Napi::Env::SetInstanceData()。这意味着插件应仅显式使用Napi::Env::GetInstanceData来检索Napi::Addon<T>类的实例。否则其作用域为全局的变量应存储为Napi::Addon<T>类的实例变量。

使用Napi::Function::New()创建的函数、使用PropertyDescriptor::Accessor()创建的访问器以及值也可以被附加。如果它们的实现需要ExampleAddon实例,可以通过Napi::Env envGetInstanceData()来获取:

cpp 复制代码
void ExampleBinding(const Napi::CallbackInfo& info) {
  ExampleAddon* addon = info.Env().GetInstanceData<ExampleAddon>();
}

方法

构造函数

创建插件的新实例。

cpp 复制代码
Napi::Addon(Napi::Env env, Napi::Object exports);
  • [输入] env:插件正在加载到的环境。
  • [输入] exports:从 JavaScript 接收的导出对象。

通常,构造函数会调用DefineAddon()以将方法、访问器和 / 或值附加到exports。如果构造函数希望替换 Node.js 提供的exports对象,它也可以创建一个新对象并将其作为第一个参数传递给DefineAddon()

DefineAddon

使用函数、访问器和 / 或值定义插件实例。

cpp 复制代码
template <typename T>
void Napi::Addon<T>::DefineAddon(Napi::Object exports,
                   const std::initializer_list<PropertyDescriptor>& properties);
  • [输入] exports:要返回给 Node.js 作为插件实例的对象。
  • [输入] properties:定义插件的方法、属性访问器和值的插件属性描述符的初始化列表。它们将被设置在exports上。参见:类属性和描述符

DefineProperties

使用插件实例方法在对象上定义函数、访问器和 / 或值属性。

cpp 复制代码
template <typename T>
Napi::Object
Napi::Addon<T>::DefineProperties(Napi::Object object,
                   const std::initializer_list<PropertyDescriptor>& properties);
  • [输入] object:将接收新属性的对象。
  • [输入] properties:要附加到object的方法、属性访问器和值的属性描述符的初始化列表。参见:类属性和描述符

返回object

相关推荐
千里马-horse13 天前
TypedArrayOf
开发语言·javascript·c++·node.js·napi
千里马-horse20 天前
CallbackInfo
c++·node.js·napi·callbackinfo
千里马-horse20 天前
Checker Tool
c++·node.js·napi
千里马-horse21 天前
node-addon-api 简介
napi
千里马-horse21 天前
BigInt
开发语言·bigint·napi·addon
千里马-horse21 天前
AsyncContext
开发语言·前端·javascript·c++·napi·asynccontext
千里马-horse21 天前
Napi::Array
开发语言·array·napi
特立独行的猫a5 个月前
C/C++三方库移植到HarmonyOS平台详细教程
c语言·c++·harmonyos·napi·三方库·aki
特立独行的猫a5 个月前
C/C++三方库移植到HarmonyOS平台详细教程(补充版so库和头文件形式)
c语言·c++·harmonyos·napi·三方库·aki