- assert断言
- async_hooks异步钩子
- async_hooks/context异步上下文
- buffer缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process子进程
- cluster集群
- CLI命令行
- console控制台
- Corepack核心包
- crypto加密
- crypto/webcrypto网络加密
- debugger调试器
- deprecation弃用
- dgram数据报
- diagnostics_channel诊断通道
- dns域名服务器
- domain域
- Error错误
- events事件触发器
- fs文件系统
- global全局变量
- http超文本传输协议
- http2超文本传输协议2.0
- https安全超文本传输协议
- inspector检查器
- Intl国际化
- module模块
- module/cjsCommonJS模块
- module/esmECMAScript模块
- module/package包模块
- net网络
- os操作系统
- path路径
- perf_hooks性能钩子
- policy安全策略
- process进程
- punycode域名代码
- querystring查询字符串
- readline逐行读取
- repl交互式解释器
- report诊断报告
- stream流
- stream/web网络流
- string_decoder字符串解码器
- test测试
- timers定时器
- tls安全传输层
- trace_events跟踪事件
- tty终端
- url网址
- util实用工具
- v8引擎
- vm虚拟机
- wasi网络汇编系统接口
- worker_threads工作线程
- zlib压缩
Node.js v18.7.0 文档
- Node.js 18.7.0
- ► 目录
-
►
索引
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS模块
- module/esm ECMAScript模块
- module/package 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- policy 安全策略
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- ► 其他版本
- 文档搜索
- 会员登录
目录
C++ 插件#
插件是用 C++ 编写的动态链接共享对象。
require()
函数可以将插件加载为普通的 Node.js 模块。
插件提供了 JavaScript 和 C/C++ 库之间的接口。
你好世界#
这个 "Hello world" 示例是一个简单的插件,用 C++ 编写,相当于以下 JavaScript 代码:
上下文感知的插件#
在某些环境中,可能需要在多个上下文中多次加载 Node.js 插件。
例如,Electron 运行时在单个进程中运行多个 Node.js 实例。
每个实例都有自己的 require()
缓存,因此当通过 require()
加载时,每个实例都需要原生插件才能正确运行。
这意味着插件必须支持多个初始化。
工作线程的支持#
为了从多个 Node.js 环境(例如主线程和工作线程)加载,插件需要:
构建#
编写源代码后,必须将其编译为二进制 addon.node
文件。
为此,请在项目的顶层创建名为 binding.gyp
的文件,使用类似 JSON 的格式描述模块的构建配置。
该文件由 node-gyp 使用,这是一个专门为编译 Node.js 插件而编写的工具。
链接到 Node.js 自带的库#
Node.js 使用静态链接库,例如 V8、libuv 和 OpenSSL。
所有插件都需要链接到 V8,也可以链接到任何其他依赖项。
通常,这就像包含适当的 #include <...>
语句(例如 #include <v8.h>
)一样简单,node-gyp
将自动定位适当的头文件。
但是,有一些注意事项需要注意:
使用 require() 加载插件#
已编译的插件二进制文件的文件扩展名是 .node
(与 .dll
或 .so
相反)。
require()
函数用于查找具有 .node
文件扩展名的文件并将它们初始化为动态链接库。
Node.js 的原生抽象#
本文档中说明的每个示例都直接使用 Node.js 和 V8 API 来实现插件。 从一个 V8 版本到下一个版本(以及一个主要的 Node.js 版本到下一个版本),V8 API 可能并且已经发生了巨大的变化。 每次更改时,插件可能需要更新和重新编译才能继续运行。 Node.js 发布计划旨在最小化此类更改的频率和影响,但 Node.js 几乎无法确保 V8 API 的稳定性。
Node-API#
Node-API 是用于构建原生插件的 API。 它独立于底层 JavaScript 运行时(例如 V8),并作为 Node.js 自身的一部分进行维护。 此 API 将在 Node.js 的各个版本中保持稳定的应用程序二进制接口 (ABI)。 它旨在将插件与底层 JavaScript 引擎中的更改隔离开来,并允许为一个版本编译的模块无需重新编译即可在更高版本的 Node.js 上运行。 插件是使用本文档中概述的相同方法/工具(node-gyp 等)构建/打包的。唯一的区别是原生代码使用的 API 集。 使用 Node-API 中可用的函数,而不是使用 V8 或 Node.js 原生抽象的 API。
插件示例#
以下是一些旨在帮助开发人员入门的示例插件。 这些示例使用 V8 API。 请参阅在线 V8 手册以获取有关各种 V8 调用的帮助,以及 V8 的嵌入器指南以获取对所使用的几个概念(例如句柄、作用域、函数模板等)的解释。
函数的参数#
插件通常会暴露可以从 Node.js 中运行的 JavaScript 访问的对象和函数。 当从 JavaScript 调用函数时,输入参数和返回值必须映射到 C/C++ 代码和从 C/C++ 代码映射。
回调#
插件中的常见做法是将 JavaScript 函数传给 C++ 函数并从那里执行它们。 以下示例说明了如何调用此类回调:
对象工厂#
插件可以从 C++ 函数中创建和返回新对象,如下例所示。
创建并返回带有属性 msg
的对象,该属性与传给 createObject()
的字符串相呼应:
函数工厂#
另一个常见的场景是创建封装 C++ 函数并将它们返回给 JavaScript 的 JavaScript 函数:
封装 C++ 对象#
还可以以允许使用 JavaScript new
运算符创建新实例的方式封装 C++ 对象/类:
封装对象的工厂#
另外,可以使用工厂模式来避免使用 JavaScript new
运算符显式创建对象实例:
传递封装的对象#
除了封装和返回 C++ 对象之外,还可以通过使用 Node.js 辅助函数 node::ObjectWrap::Unwrap
将它们解包来传递被包装的对象。
以下示例显示了函数 add()
,它可以将两个 MyObject
对象作为输入参数: