- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- FFI 外部函数接口
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/iter 可迭代流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- zlib/iter 可迭代压缩
Node.js v26.2.0 文档
- Node.js v26.2.0
-
目录
- FFI
- 概述
- 类型名称
- 标志性物品
ffi.suffixffi.dlopen(path[, definitions])ffi.dlclose(handle)ffi.dlsym(handle, symbol)- 类:
DynamicLibrarynew DynamicLibrary(path)library.pathlibrary.functionslibrary.symbolslibrary.close()library[Symbol.dispose]()library.getFunction(name, signature)library.getFunctions([definitions])library.getSymbol(name)library.getSymbols()library.registerCallback([signature,] callback)library.unregisterCallback(pointer)library.refCallback(pointer)library.unrefCallback(pointer)
- 调用本地函数
- 原始内存访问辅助工具
ffi.toString(pointer)ffi.toBuffer(pointer, length[, copy])ffi.toArrayBuffer(pointer, length[, copy])ffi.exportString(string, pointer, length[, encoding])ffi.exportBuffer(buffer, pointer, length)ffi.exportArrayBuffer(arrayBuffer, pointer, length)ffi.exportArrayBufferView(arrayBufferView, pointer, length)ffi.getRawPointer(source)- 安全说明
- FFI
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- FFI 外部函数接口
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/iter 可迭代流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- zlib/iter 可迭代压缩
FFI#>
源代码: lib/ffi.js
node:ffi 模块提供了一个实验性的外部函数接口,用于从 JavaScript 加载动态库并调用本地符号。
🌐 The node:ffi module provides an experimental foreign function interface for
loading dynamic libraries and calling native symbols from JavaScript.
此 API 不安全。传递无效指针、使用错误的符号签名或在内存被释放后访问内存可能会导致进程崩溃或内存损坏。
🌐 This API is unsafe. Passing invalid pointers, using an incorrect symbol signature, or accessing memory after it has been freed can crash the process or corrupt memory.
要访问它:
🌐 To access it:
import ffi from 'node:ffi';const ffi = require('node:ffi');
该模块仅在具有 FFI 支持的构建中以 node: 方案可用,并受 --experimental-ffi 标志控制。
🌐 This module is only available under the node: scheme in builds with FFI
support and is gated by the --experimental-ffi flag.
在 libffi 提供兼容静态后端的平台上,通过打包的 libffi 可以构建支持 node:ffi 的 Node.js,或者使用 --shared-ffi 配置标志通过共享的 libffi 实现。
非官方的 GN 构建不支持 node:ffi。
🌐 Building Node.js with node:ffi support is available via the bundled libffi on
platforms where libffi provides a compatible static backend, or via a
shared libffi using the --shared-ffi configure flag.
The unofficial GN build does not support node:ffi.
打包的 libffi 不支持以下目标:
🌐 The following targets are not supported by bundled libffi:
s390x.mips、mipsel和mips64el在除 FreeBSD、Linux 和 OpenBSD 之外的目标上。ppc64在 Android、CloudABI、iOS、OpenHarmony、OS/400、Solaris 和 Windows 上。
使用 权限模型 时,除非提供 --allow-ffi 标志,否则 FFI API 会受到限制。
🌐 When using the Permission Model, FFI APIs are
restricted unless the --allow-ffi flag is provided.
概述#>
🌐 Overview
node:ffi 模块暴露了两组 API:
🌐 The node:ffi module exposes two groups of APIs:
- 用于加载库、解析符号和创建可调用 JavaScript 封装器的动态库 API。
- 用于通过指针读取和写入原始值、将指针转换为 JavaScript 字符串、
Buffer实例和ArrayBuffer实例,以及将数据复制回本地内存的原始内存助手。
类型名称#>
🌐 Type names
FFI 签名使用字符串类型名称。
🌐 FFI signatures use string type names.
支持的类型名称:
🌐 Supported type names:
voidi8,int8u8、uint8、bool、chari16,int16u16,uint16i32,int32u32,uint32i64,int64u64,uint64f32,floatf64,doublepointer,ptrstring,strbufferarraybufferfunction
这些类型名称也作为常量暴露在 ffi.types 上:
🌐 These type names are also exposed as constants on ffi.types:
ffi.types.VOID='void'ffi.types.POINTER='pointer'ffi.types.BUFFER='buffer'ffi.types.ARRAY_BUFFER='arraybuffer'ffi.types.FUNCTION='function'ffi.types.BOOL='bool'ffi.types.CHAR='char'ffi.types.STRING='string'ffi.types.FLOAT='float'ffi.types.DOUBLE='double'ffi.types.INT_8='int8'ffi.types.UINT_8='uint8'ffi.types.INT_16='int16'ffi.types.UINT_16='uint16'ffi.types.INT_32='int32'ffi.types.UINT_32='uint32'ffi.types.INT_64='int64'ffi.types.UINT_64='uint64'ffi.types.FLOAT_32='float32'ffi.types.FLOAT_64='float64'
类似指针的类型(pointer、string、buffer、arraybuffer 和 function)都会作为指针通过本地层传递。
🌐 Pointer-like types (pointer, string, buffer, arraybuffer, and
function) are all passed through the native layer as pointers.
当将 Buffer、ArrayBuffer 或类型化数组的值作为类似指针的参数传递时,Node.js 会在本地调用期间借用它们底层内存的原始指针。调用者必须确保底层存储在整个调用期间保持有效和稳定。
🌐 When Buffer, ArrayBuffer, or typed array values are passed as pointer-like
arguments, Node.js borrows a raw pointer to their backing memory for the
duration of the native call. The caller must ensure that backing store remains
valid and stable for the entire call.
在原生调用处于活动状态时调整大小、传输、分离或以其他方式使该后备存储无效是不受支持且危险的,包括通过可重入的 JavaScript(例如 FFI 回调)进行操作。这样做可能会导致进程崩溃、产生错误输出或损坏内存。
🌐 It is unsupported and dangerous to resize, transfer, detach, or otherwise invalidate that backing store while the native call is active, including through reentrant JavaScript such as FFI callbacks. Doing so may crash the process, produce incorrect output, or corrupt memory.
char 类型遵循平台 C ABI。在普通 C char 为有符号的平 台上,它的行为类似于 i8;否则,它的行为类似于 u8。
🌐 The char type follows the platform C ABI. On platforms where plain C char
is signed it behaves like i8; otherwise it behaves like u8.
bool 类型被编组为 8 位无符号整数。传递诸如 0 和 1 的数值;不接受 JavaScript 的 true 和 false。
🌐 The bool type is marshaled as an 8-bit unsigned integer. Pass numeric values
such as 0 and 1; JavaScript true and false are not accepted.
标志性物品#>
🌐 Signature objects
函数和回调使用签名对象来描述。
🌐 Functions and callbacks are described with signature objects.
支持的字段:
🌐 Supported fields:
result、return或returns作为返回类型。parameters或arguments用于参数类型列表。
在单个签名对象中,只能存在一个返回类型字段和一个参数列表字段。
🌐 Only one return-type field and one parameter-list field may be present in a single signature object.
const signature = {
result: 'i32',
parameters: ['i32', 'i32'],
};
ffi.suffix#>
当前平台的本地共享库后缀:
🌐 The native shared library suffix for the current platform:
'dylib'在 macOS 上'so'在类 Unix 平台上'dll'在 Windows 上
这可以用来构建可移植的库路径:
🌐 This can be used to build portable library paths:
const { suffix } = require('node:ffi');
const path = `libsqlite3.${suffix}`;
ffi.dlopen(path[, definitions])#>
加载动态库并解析所请求的函数定义。
🌐 Loads a dynamic library and resolves the requested function definitions.
在 Windows 上不支持传递 null。
🌐 On Windows passing null is not supported.
当省略 definitions 时,functions 会作为一个空对象返回,直到显式解析符号为止。
🌐 When definitions is omitted, functions is returned as an empty object until
symbols are resolved explicitly.
返回的对象包含:
🌐 The returned object contains:
libDynamicLibrary 已加载的库句柄。functions<Object> 所请求符号的可调用封装器。
返回的对象还实现了显式资源管理协议,因此可以与 using 声明一起使用。释放返回的对象会关闭库句柄。
🌐 The returned object also implements the explicit resource management protocol,
so it can be used with the using declaration. Disposing the returned
object closes the library handle.
import { dlopen } from 'node:ffi';
{
using handle = dlopen('./mylib.so', {
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
});
console.log(handle.functions.add_i32(20, 22));
} // handle.lib.close() is invoked automatically here.
import { dlopen } from 'node:ffi';
const { lib, functions } = dlopen('./mylib.so', {
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
string_length: { parameters: ['pointer'], result: 'u64' },
});
console.log(functions.add_i32(20, 22));
const { dlopen } = require('node:ffi');
const { lib, functions } = dlopen('./mylib.so', {
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
string_length: { parameters: ['pointer'], result: 'u64' },
});
console.log(functions.add_i32(20, 22));
ffi.dlclose(handle)#>
handleDynamicLibrary
关闭一个动态库。
🌐 Closes a dynamic library.
这相当于调用 handle.close()。
🌐 This is equivalent to calling handle.close().
ffi.dlsym(handle, symbol)#>
从已加载的库中解析符号地址。
🌐 Resolves a symbol address from a loaded library.
这相当于调用 handle.getSymbol(symbol)。
🌐 This is equivalent to calling handle.getSymbol(symbol).
类:DynamicLibrary#>
🌐 Class: DynamicLibrary
表示已加载的动态库。
🌐 Represents a loaded dynamic library.
new DynamicLibrary(path)#>
加载动态库而不急于解析任何函数。
🌐 Loads the dynamic library without resolving any functions eagerly.
在 Windows 上不支持传递 null。
🌐 On Windows passing null is not supported.
const { DynamicLibrary } = require('node:ffi');
const lib = new DynamicLibrary('./mylib.so');
library.path#>
用于加载库的路径。
🌐 The path used to load the library.
library.functions#>
一个包含先前解析过的函数封装器的对象。
🌐 An object containing previously resolved function wrappers.
library.symbols#>
一个包含先前解析的符号地址作为 bigint 值的对象。
🌐 An object containing previously resolved symbol addresses as bigint values.
library.close()#>
关闭库句柄。
🌐 Closes the library handle.
DynamicLibrary 实现了显式资源管理协议,因此可以使用 using 声明来管理库实例。离开封闭作用域会自动调用 library.close()。
import { DynamicLibrary } from 'node:ffi';
{
using lib = new DynamicLibrary('./mylib.so');
// Use `lib` here; `lib.close()` is called when the block exits.
}
多次调用 library.close()(或释放库)不会有任何效果。
🌐 Calling library.close() (or disposing the library) more than once is a no-op.
在库关闭之后:
🌐 After a library has been closed:
- 已解析的函数封装器失效。
- 进一步的符号和函数解析会抛出异常。
- 已注册的回调被作废。
关闭一个库并不会使以前导出的回调指针可以安全重用。Node.js 不会跟踪或撤销已经交给本地代码的回调指针。
🌐 Closing a library does not make previously exported callback pointers safe to reuse. Node.js does not track or revoke callback pointers that have already been handed to native code.
如果本地代码在 library.close() 之后或在 library.unregisterCallback(pointer) 之后仍然持有回调指针,调用该指针将具有未定义行为,这是不允许的,也是危险的:它可能导致进程崩溃、产生错误输出或损坏内存。本地代码必须在库关闭之前或回调注销之前停止使用回调地址。
🌐 If native code still holds a callback pointer after library.close() or after
library.unregisterCallback(pointer), invoking that pointer has undefined
behavior, is not allowed, and is dangerous: it can crash the process, produce
incorrect output, or corrupt memory. Native code must stop using callback
addresses before the library is closed or before the callback is unregistered.
从库的某个活动回调中调用 library.close() 是不支持且危险的。回调必须在库关闭之前返回。
🌐 Calling library.close() from one of the library's active callbacks is
unsupported and dangerous. The callback must return before the library is
closed.
library[Symbol.dispose]()#>
调用 library.close()。这允许 DynamicLibrary 实例与 using 声明一起使用,以便在封闭的作用域退出时自动清理。在已关闭的库上,此操作无效。
🌐 Calls library.close(). This allows DynamicLibrary instances to be used with
the using declaration for automatic cleanup when the enclosing scope
exits. It is a no-op on a library that has already been closed.
library.getFunction(name, signature)#>
name<string>signature<Object>- 返回:<Function>
解析一个符号并返回一个可调用的 JavaScript 封装器。
🌐 Resolves a symbol and returns a callable JavaScript wrapper.
返回的函数有一个 .pointer 属性,包含作为 bigint 的原生函数地址。
🌐 The returned function has a .pointer property containing the native function
address as a bigint.
如果相同的符号已经被解析,再用不同的签名请求它会抛出异常。
🌐 If the same symbol has already been resolved, requesting it again with a different signature throws.
const { DynamicLibrary } = require('node:ffi');
const lib = new DynamicLibrary('./mylib.so');
const add = lib.getFunction('add_i32', {
parameters: ['i32', 'i32'],
result: 'i32',
});
console.log(add(20, 22));
console.log(add.pointer);
library.getFunctions([definitions])#>
当提供 definitions 时,解析每个命名符号并返回一个包含可调用封装器的对象。
🌐 When definitions is provided, resolves each named symbol and returns an
object containing callable wrappers.
当省略 definitions 时,返回库中所有已解析函数的封装器。
🌐 When definitions is omitted, returns wrappers for all functions that have
already been resolved on the library.
library.getSymbol(name)#>
解析符号并返回其本地地址作为 bigint。
🌐 Resolves a symbol and returns its native address as a bigint.
library.getSymbols()#>
- 返回:<Object>
返回一个包含所有先前解析的符号地址的对象。
🌐 Returns an object containing all previously resolved symbol addresses.
library.registerCallback([signature,] callback)#>
signature<Object>callback<Function>- 返回:<bigint>
创建由 JavaScript 函数支持的本地回调指针。
🌐 Creates a native callback pointer backed by a JavaScript function.
当省略 signature 时,回调使用默认的 void () 签名。
🌐 When signature is omitted, the callback uses a default void () signature.
返回值是作为 bigint 的回调指针地址。它可以传递给期望回调指针的本地函数。
🌐 The return value is the callback pointer address as a bigint. It can be
passed to native functions expecting a callback pointer.
const { DynamicLibrary } = require('node:ffi');
const lib = new DynamicLibrary('./mylib.so');
const callback = lib.registerCallback(
{ parameters: ['i32'], result: 'i32' },
(value) => value * 2,
);
回调受到以下限制:
🌐 Callbacks are subject to the following restrictions:
- 它们必须在创建它们的同一系统线程上被调用。
- 它们不得抛出异常。
- 他们不能食言。
- 它们必须返回与声明的结果类型兼容的值。
- 他们在运行时不得在其拥有的库上调用
library.close()。 - 他们在运行时绝不能注销自己。
从回调内部关闭拥有的库或注销当前正在执行的回调是不支持且危险的。这样做可能会导致进程崩溃、产生错误的输出或损坏内存。
🌐 Closing the owning library or unregistering the currently executing callback from inside the callback is unsupported and dangerous. Doing so may crash the process, produce incorrect output, or corrupt memory.
library.unregisterCallback(pointer)#>
pointer<bigint>
释放之前使用 library.registerCallback() 创建的回调。
🌐 Releases a callback previously created with library.registerCallback().
调用 library.unregisterCallback(pointer) 以执行当前正在运行的回调是不支持且危险的。回调必须在被取消注册之前返回。
🌐 Calling library.unregisterCallback(pointer) for a callback that is currently
executing is unsupported and dangerous. The callback must return before it is
unregistered.
在 library.unregisterCallback(pointer) 返回后,从本地代码调用该回调指针具有未定义行为,这是不允许的,而且很危险:它可能导致进程崩溃、产生错误的输出或破坏内存。
🌐 After library.unregisterCallback(pointer) returns, invoking that callback
pointer from native code has undefined behavior, is not allowed, and is
dangerous: it can crash the process, produce incorrect output, or corrupt
memory.
library.refCallback(pointer)#>
pointer<bigint>
保持回调在 JavaScript 中被强引用。
🌐 Keeps the callback strongly referenced by JavaScript.
library.unrefCallback(pointer)#>
pointer<bigint>
允许回调被 JavaScript 弱引用。
🌐 Allows the callback to become weakly referenced by JavaScript.
如果回调函数随后被垃圾回收,后续的本地调用将变为无操作。非空返回值在返回给本地代码之前会被初始化为零。
🌐 If the callback function is later garbage collected, subsequent native invocations become a no-op. Non-void return values are zero-initialized before returning to native code.
调用本地函数#>
🌐 Calling native functions
参数转换取决于声明的 FFI 类型。
🌐 Argument conversion depends on the declared FFI type.
对于 8 位、16 位和 32 位整数类型以及浮点类型,请传递与声明类型匹配的 JavaScript number 值。
🌐 For 8-, 16-, and 32-bit integer types and for floating-point types, pass
JavaScript number values that match the declared type.
对于 64 位整数类型(i64 和 u64),传递 JavaScript bigint 值。
🌐 For 64-bit integer types (i64 and u64), pass JavaScript bigint values.
对于指针类参数:
🌐 For pointer-like parameters:
null和undefined被传递为空指针。string值在调用期间被复制到临时的 NUL 结尾 UTF-8 字符串中。Buffer、类型化数组和DataView实例会传递一个指向其后备内存的指针。ArrayBuffer传递其底层内存的指针。bigint值作为原始指针地址传递。
指针返回值以 bigint 地址的形式显示。
🌐 Pointer return values are exposed as bigint addresses.
原始内存访问辅助工具#>
🌐 Primitive memory access helpers
以下辅助工具可以在本地指针处读写原始值,也可以选择使用字节偏移:
🌐 The following helpers read and write primitive values at a native pointer, optionally with a byte offset:
ffi.getInt8(pointer[, offset])ffi.getUint8(pointer[, offset])ffi.getInt16(pointer[, offset])ffi.getUint16(pointer[, offset])ffi.getInt32(pointer[, offset])ffi.getUint32(pointer[, offset])ffi.getInt64(pointer[, offset])ffi.getUint64(pointer[, offset])ffi.getFloat32(pointer[, offset])ffi.getFloat64(pointer[, offset])ffi.setInt8(pointer, offset, value)ffi.setUint8(pointer, offset, value)ffi.setInt16(pointer, offset, value)ffi.setUint16(pointer, offset, value)ffi.setInt32(pointer, offset, value)ffi.setUint32(pointer, offset, value)ffi.setInt64(pointer, offset, value)ffi.setUint64(pointer, offset, value)ffi.setFloat32(pointer, offset, value)ffi.setFloat64(pointer, offset, value)
这些助手执行直接的内存读写。pointer 必须是一个 bigint,指向有效的可读或可写的原生内存。提供 offset 时,会将其解释为从 pointer 开始的字节偏移。
🌐 These helpers perform direct memory reads and writes. pointer must be a
bigint referring to valid readable or writable native memory. offset, when
provided, is interpreted as a byte offset from pointer.
getter 辅助函数为 8 位、16 位和 32 位整数类型以及浮点类型返回 JavaScript number 值。它们为 64 位整数类型返回 bigint 值。
🌐 The getter helpers return JavaScript number values for 8-, 16-, and 32-bit
integer types and for floating-point types. They return bigint values for
64-bit integer types.
设置器辅助函数需要一个明确的字节偏移量,并在将提供的 JavaScript 值写入内存之前验证其与目标原生类型的匹配。
对于 setInt64() 和 setUint64(),bigint 值可以直接接受;
数字输入必须是 JavaScript 安全整数范围内的整数。
🌐 The setter helpers require an explicit byte offset and validate the supplied
JavaScript value against the target native type before writing it into memory.
For setInt64() and setUint64(), bigint values are accepted directly;
numeric inputs must be integers within JavaScript's safe integer range.
const {
getInt32,
setInt32,
} = require('node:ffi');
setInt32(ptr, 0, 42);
console.log(getInt32(ptr, 0));
像本模块中的其他原始内存辅助函数一样,这些 API 不跟踪所有权、边界或生命周期。传递无效指针、使用错误的偏移量或通过过期指针写入都可能破坏内存或导致进程崩溃。
🌐 Like the other raw memory helpers in this module, these APIs do not track ownership, bounds, or lifetime. Passing an invalid pointer, using the wrong offset, or writing through a stale pointer can corrupt memory or crash the process.
ffi.toString(pointer)#>
从本地内存读取以 NUL 结尾的 UTF-8 字符串。
🌐 Reads a NUL-terminated UTF-8 string from native memory.
如果 pointer 是 0n,则返回 null。
🌐 If pointer is 0n, null is returned.
此函数不会验证 pointer 是否指向可读内存,也不会验证所指向的数据是否以 \0 结尾。传递无效指针、指向已释放内存的指针或指向没有终止 NUL 的字节的指针,可能会读取无关的内存、导致进程崩溃,或产生截断或乱码输出。
🌐 This function does not validate that pointer refers to readable memory or
that the pointed-to data is terminated with \0. Passing an invalid pointer,
a pointer to freed memory, or a pointer to bytes without a terminating NUL can
read unrelated memory, crash the process, or produce truncated or garbled
output.
const { toString } = require('node:ffi');
const value = toString(ptr);
ffi.toBuffer(pointer, length[, copy])#>
从本地内存创建一个 Buffer。
🌐 Creates a Buffer from native memory.
当 copy 为 true 时,返回的 Buffer 拥有其自己的复制内存。
当 copy 为 false 时,返回的 Buffer 直接引用原始本地内存。
🌐 When copy is true, the returned Buffer owns its own copied memory.
When copy is false, the returned Buffer references the original native
memory directly.
使用 copy: false 是一种零拷贝的应急方法。返回的 Buffer 是一个可写的外部内存视图,因此在 JavaScript 中的写入会直接更新原始本地内存。调用者必须保证:
🌐 Using copy: false is a zero-copy escape hatch. The returned Buffer is a
writable view onto foreign memory, so writes in JavaScript update the original
native memory directly. The caller must guarantee that:
pointer在返回的Buffer的整个生命周期内保持有效。length保持在分配的本地区域内。- 在 JavaScript 仍然使用
Buffer的情况下,没有本地代码会释放或重新利用那块内存。 - 内存保护被遵守。例如,只读内存页不得被写入。
如果这些保证未被满足,读取或写入 Buffer 可能会破坏内存或导致进程崩溃。
🌐 If these guarantees are not met, reading or writing the Buffer can corrupt
memory or crash the process.
ffi.toArrayBuffer(pointer, length[, copy])#>
pointer<bigint>length<number>copy<boolean> 当false,创建一个零拷贝视图。默认:true。- 返回:<ArrayBuffer>
从本地内存创建一个 ArrayBuffer。
🌐 Creates an ArrayBuffer from native memory.
当 copy 为 true 时,返回的 ArrayBuffer 包含复制的字节。
当 copy 为 false 时,返回的 ArrayBuffer 直接引用原始本地内存。
🌐 When copy is true, the returned ArrayBuffer contains copied bytes.
When copy is false, the returned ArrayBuffer references the original
native memory directly.
与 ffi.toBuffer(pointer, length, copy) 描述的相同生命周期和边界要求适用于这里。使用 copy: false 时,返回的 ArrayBuffer 是对外部内存的零拷贝视图,并且只有在该内存保持分配状态、布局未改变且在整个暴露范围内有效时才安全。
🌐 The same lifetime and bounds requirements described for
ffi.toBuffer(pointer, length, copy) apply
here. With copy: false, the
returned ArrayBuffer is a zero-copy view of foreign memory and is only safe
while that memory remains allocated, unchanged in layout, and valid for the
entire exposed range.
ffi.exportString(string, pointer, length[, encoding])#>
将 JavaScript 字符串复制到本地内存并附加一个尾随的 NUL 终止符。
🌐 Copies a JavaScript string into native memory and appends a trailing NUL terminator.
length 必须足够大,以容纳完整的编码字符串以及结尾的 NUL 终止符。对于 UTF-16 和 UCS-2 编码,结尾的终止符使用两个零字节。
pointer 必须指向具有至少 length 字节可用存储空间的可写本地内存。此函数不会自行分配内存。
string 必须是一个 JavaScript 字符串。encoding 必须是一个字符串。
ffi.exportBuffer(buffer, pointer, length)#>
将字节从 Buffer 复制到本地内存。
🌐 Copies bytes from a Buffer into native memory.
length 必须至少为 buffer.length。
pointer 必须指向具有至少 length 字节可用存储空间的可写本地内存。此函数不会自行分配内存。
buffer 必须是一个 Node.js Buffer。
ffi.exportArrayBuffer(arrayBuffer, pointer, length)#>
arrayBuffer<ArrayBuffer>pointer<bigint>length<number>
将字节从 ArrayBuffer 复制到本地内存。
🌐 Copies bytes from an ArrayBuffer into native memory.
length 必须至少为 arrayBuffer.byteLength。
pointer 必须指向具有至少 length 字节可用存储空间的可写本地内存。此函数不会自行分配内存。
ffi.exportArrayBufferView(arrayBufferView, pointer, length)#>
arrayBufferView<ArrayBufferView>pointer<bigint>length<number>
将字节从 ArrayBufferView 复制到本地内存。
🌐 Copies bytes from an ArrayBufferView into native memory.
length 必须至少为 arrayBufferView.byteLength。
pointer 必须指向具有至少 length 字节可用存储空间的可写本地内存。此函数不会自行分配内存。
ffi.getRawPointer(source)#>
source<Buffer> | <ArrayBuffer> | <ArrayBufferView>- 返回:<bigint>
返回由 JavaScript 管理的字节存储的原始内存地址。
🌐 Returns the raw memory address of JavaScript-managed byte storage.
这是不安全且危险的。如果底层内存被分离、调整大小、转移或以其他方式失效,返回的指针可能会变得无效。使用过时的指针可能导致内存损坏或进程崩溃。
🌐 This is unsafe and dangerous. The returned pointer can become invalid if the underlying memory is detached, resized, transferred, or otherwise invalidated. Using stale pointers can cause memory corruption or process crashes.
安全说明#>
🌐 Safety notes
node:ffi 模块不跟踪指针有效性、内存所有权或本地对象的生命周期。
🌐 The node:ffi module does not track pointer validity, memory ownership, or
native object lifetimes.
特别是:
🌐 In particular:
- 不要从已释放的内存中读取或向其写入。
- 在本地内存被释放后,不要使用零拷贝视图。
- 不要为本地符号声明错误的签名。
- 在本地代码可能仍会调用回调时,不要取消注册回调。
- 在
library.close()或library.unregisterCallback(pointer)之后不要调用回调指针。 - 假设未定义的回调行为可能会导致进程崩溃、产生错误的输出或破坏内存。
- 不要假设指针返回值意味着所有权;调用者是否必须释放返回的地址完全取决于本地 API。
一般来说,除非需要零拷贝访问,否则应优先使用复制的值,并在本地端显式保持回调和指针的生命周期。
🌐 As a general rule, prefer copied values unless zero-copy access is required, and keep callback and pointer lifetimes explicit on the native side.