mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
The `#sec-using-declarations` fragment does not exist in the explicit resource management proposal, so the link silently resolves to the top of the page. The proposal defines `using` under `#sec-let-and-const-declarations`, and the only `using`-related section ids are static semantics entries. Point the reference at the MDN page for `using` instead, matching the `[`using`]` definition already used in fs.md. Signed-off-by: Soul Lee <alus20x@gmail.com> PR-URL: https://github.com/nodejs/node/pull/65632 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
805 lines
25 KiB
Markdown
805 lines
25 KiB
Markdown
# FFI
|
|
|
|
<!--introduced_in=v26.1.0-->
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
> Stability: 1 - Experimental
|
|
|
|
<!-- source_link=lib/ffi.js -->
|
|
|
|
The `node:ffi` module provides an experimental foreign function interface for
|
|
loading dynamic libraries and calling native symbols from JavaScript.
|
|
|
|
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:
|
|
|
|
```mjs
|
|
import ffi from 'node:ffi';
|
|
```
|
|
|
|
```cjs
|
|
const ffi = require('node:ffi');
|
|
```
|
|
|
|
This module is only available under the `node:` scheme in builds with FFI
|
|
support. It can be disabled with the `--no-experimental-ffi` flag.
|
|
|
|
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`.
|
|
|
|
The following targets are not supported by bundled libffi:
|
|
|
|
* `s390x`.
|
|
* `mips`, `mipsel`, and `mips64el` on targets other than FreeBSD, Linux, and
|
|
OpenBSD.
|
|
* `ppc64` on Android, CloudABI, iOS, OpenHarmony, OS/400, Solaris, and Windows.
|
|
|
|
When using the [Permission Model][], FFI APIs are
|
|
restricted unless the [`--allow-ffi`][] flag is provided.
|
|
|
|
## Overview
|
|
|
|
The `node:ffi` module exposes two groups of APIs:
|
|
|
|
* Dynamic library APIs for loading libraries, resolving symbols, and creating
|
|
callable JavaScript wrappers.
|
|
* Raw memory helpers for reading and writing primitive values through pointers,
|
|
converting pointers to JavaScript strings, `Buffer` instances, and
|
|
`ArrayBuffer` instances, and for copying data back into native memory.
|
|
|
|
## Type names
|
|
|
|
FFI signatures use string type names.
|
|
|
|
Supported type names:
|
|
|
|
* `void`
|
|
* `char`
|
|
* `int8`
|
|
* `uint8`
|
|
* `int16`
|
|
* `uint16`
|
|
* `int32`
|
|
* `uint32`
|
|
* `int64`
|
|
* `uint64`
|
|
* `float32`
|
|
* `float64`
|
|
* `pointer`
|
|
* `string`
|
|
* `buffer`
|
|
* `arraybuffer`
|
|
* `function`
|
|
|
|
<details>
|
|
<summary>Alternative spellings</summary>
|
|
|
|
* `i8` for `int8`
|
|
* `u8` and `bool` for `uint8`
|
|
* `i16` for `int16`
|
|
* `u16` for `uint16`
|
|
* `i32` for `int32`
|
|
* `u32` for `uint32`
|
|
* `i64` for `int64`
|
|
* `u64` for `uint64`
|
|
* `f32` and `float` for `float32`
|
|
* `f64` and `double` for `float64`
|
|
* `ptr` for `pointer`
|
|
* `str` for `string`
|
|
|
|
</details>
|
|
|
|
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-like types (`pointer`, `string`, `buffer`, `arraybuffer`, and
|
|
`function`) are all passed through the native layer as pointers.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
The `char` type follows the platform C ABI. On platforms where plain C `char`
|
|
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
|
|
|
|
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.
|
|
|
|
On optimized Fast FFI calls, `pointer` and `function` parameters accept raw
|
|
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
|
|
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
|
|
on the JavaScript side before calling the optimized native wrapper.
|
|
|
|
Optimized Fast FFI calls fall back to the generic FFI call path when a
|
|
function's arguments or return type do not fit the platform-specific fast
|
|
trampoline. Fast FFI calls support at most 8 total arguments, and the
|
|
register and argument limits differ per architecture:
|
|
|
|
| Architecture | Max integer/pointer args | Max floating-point args | Buffer-shaped args | Buffer-shaped + FP together | Narrow (8/16-bit) return |
|
|
| -------------------------- | ----------------------------------------- | ----------------------- | ------------------ | --------------------------- | ------------------------ |
|
|
| AArch64 | 7 (6 when a buffer-shaped arg is present) | 8 | Supported | Not supported | Supported |
|
|
| x86-64, Linux/macOS (SysV) | 6 (4 when a buffer-shaped arg is present) | 8 | Supported | Not supported | Supported |
|
|
| x86-64, Windows (Win64) | 3 (total arguments also capped at 3) | 3 | Not supported | N/A | Supported |
|
|
| s390x | 4 | 4 | Not supported | N/A | Not supported |
|
|
| PPC64LE | 7 | 8 | Not supported | N/A | Not supported |
|
|
| LoongArch64 | 7 | 8 | Not supported | N/A | Not supported |
|
|
| RISC-V (64-bit) | 7 | 8 | Not supported | N/A | Not supported |
|
|
|
|
PPC64BE has no fast-call trampoline and always uses the generic call path.
|
|
"Buffer-shaped args" means `Buffer`, typed array, `DataView`, or `ArrayBuffer`
|
|
values passed as pointer-like arguments. Functions whose argument or return
|
|
types exceed the limits for the current platform use the generic FFI call
|
|
path instead.
|
|
|
|
## Signature objects
|
|
|
|
Functions and callbacks are described with signature objects.
|
|
|
|
Signature objects may contain the following properties, both of which are
|
|
optional:
|
|
|
|
* `return` {string} A [type name][type names] specifying the return type of the
|
|
function or callback. **Default:** `'void'`.
|
|
* `arguments` {string\[]} An array of [type names][] specifying the argument
|
|
type list of the function or callback. **Default:** `[]`.
|
|
|
|
```js
|
|
const signature = {
|
|
return: 'int32',
|
|
arguments: ['int32', 'int32'],
|
|
};
|
|
```
|
|
|
|
## `ffi.suffix`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* {string}
|
|
|
|
The native shared library suffix for the current platform:
|
|
|
|
* `'dylib'` on macOS
|
|
* `'so'` on Unix-like platforms
|
|
* `'dll'` on Windows
|
|
|
|
This can be used to build portable library paths:
|
|
|
|
```cjs
|
|
const { suffix } = require('node:ffi');
|
|
|
|
const path = `libsqlite3.${suffix}`;
|
|
```
|
|
|
|
## `ffi.dlopen(path[, definitions])`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `path` {string|null} Path to a dynamic library, or `null` to resolve symbols
|
|
from the current process image.
|
|
* `definitions` {Object} Symbol definitions to resolve immediately.
|
|
* Returns: {Object}
|
|
|
|
Loads a dynamic library and resolves the requested function definitions.
|
|
|
|
On Windows passing `null` is not supported.
|
|
|
|
When `definitions` is omitted, `functions` is returned as an empty object until
|
|
symbols are resolved explicitly.
|
|
|
|
The returned object contains:
|
|
|
|
* `lib` {DynamicLibrary} The loaded library handle.
|
|
* `functions` {Object} Callable wrappers for the requested symbols.
|
|
|
|
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.
|
|
|
|
```mjs
|
|
import { dlopen, suffix } from 'node:ffi';
|
|
|
|
{
|
|
using handle = dlopen(`./mylib.${suffix}`, {
|
|
add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
|
|
});
|
|
console.log(handle.functions.add_i32(20, 22));
|
|
} // handle.lib.close() is invoked automatically here.
|
|
```
|
|
|
|
```mjs
|
|
import { dlopen, suffix } from 'node:ffi';
|
|
|
|
const { lib, functions } = dlopen(`./mylib.${suffix}`, {
|
|
add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
|
|
string_length: { arguments: ['pointer'], return: 'uint64' },
|
|
});
|
|
|
|
console.log(functions.add_i32(20, 22));
|
|
```
|
|
|
|
```cjs
|
|
const { dlopen, suffix } = require('node:ffi');
|
|
|
|
const { lib, functions } = dlopen(`./mylib.${suffix}`, {
|
|
add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
|
|
string_length: { arguments: ['pointer'], return: 'uint64' },
|
|
});
|
|
|
|
console.log(functions.add_i32(20, 22));
|
|
```
|
|
|
|
## `ffi.dlclose(handle)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `handle` {DynamicLibrary}
|
|
|
|
Closes a dynamic library.
|
|
|
|
This is equivalent to calling `handle.close()`.
|
|
|
|
## `ffi.dlsym(handle, symbol)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `handle` {DynamicLibrary}
|
|
* `symbol` {string}
|
|
* Returns: {bigint}
|
|
|
|
Resolves a symbol address from a loaded library.
|
|
|
|
This is equivalent to calling `handle.getSymbol(symbol)`.
|
|
|
|
## Class: `DynamicLibrary`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
Represents a loaded dynamic library.
|
|
|
|
### `new DynamicLibrary(path)`
|
|
|
|
* `path` {string|null} Path to a dynamic library, or `null` to resolve symbols
|
|
from the current process image.
|
|
|
|
Loads the dynamic library without resolving any functions eagerly.
|
|
|
|
On Windows passing `null` is not supported.
|
|
|
|
```cjs
|
|
const { DynamicLibrary, suffix } = require('node:ffi');
|
|
|
|
const lib = new DynamicLibrary(`./mylib.${suffix}`);
|
|
```
|
|
|
|
### `library.path`
|
|
|
|
* {string}
|
|
|
|
The path used to load the library.
|
|
|
|
### `library.functions`
|
|
|
|
* {Object}
|
|
|
|
An object containing previously resolved function wrappers.
|
|
|
|
### `library.symbols`
|
|
|
|
* {Object}
|
|
|
|
An object containing previously resolved symbol addresses as `bigint` values.
|
|
|
|
### `library.close()`
|
|
|
|
Closes the library handle.
|
|
|
|
`DynamicLibrary` implements the explicit resource management protocol, so a
|
|
library instance can be managed with the [`using`][] declaration. Leaving the
|
|
enclosing scope invokes `library.close()` automatically.
|
|
|
|
```mjs
|
|
import { DynamicLibrary, suffix } from 'node:ffi';
|
|
|
|
{
|
|
using lib = new DynamicLibrary(`./mylib.${suffix}`);
|
|
// Use `lib` here; `lib.close()` is called when the block exits.
|
|
}
|
|
```
|
|
|
|
Calling `library.close()` (or disposing the library) more than once is a no-op.
|
|
|
|
After a library has been closed:
|
|
|
|
* Resolved function wrappers become invalid.
|
|
* Further symbol and function resolution throws.
|
|
* Registered callbacks are invalidated.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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]()`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
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}
|
|
* Returns: {Function}
|
|
|
|
Resolves a symbol and returns a callable JavaScript wrapper.
|
|
|
|
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. Requesting it again with the same signature returns
|
|
the same function, as does reading it from [`library.functions`][].
|
|
|
|
```cjs
|
|
const { DynamicLibrary, suffix } = require('node:ffi');
|
|
|
|
const lib = new DynamicLibrary(`./mylib.${suffix}`);
|
|
const add = lib.getFunction('add_i32', {
|
|
arguments: ['int32', 'int32'],
|
|
return: 'int32',
|
|
});
|
|
|
|
console.log(add(20, 22));
|
|
console.log(add.pointer);
|
|
```
|
|
|
|
### `library.getFunctions([definitions])`
|
|
|
|
* `definitions` {Object}
|
|
* Returns: {Object}
|
|
|
|
When `definitions` is provided, resolves each named symbol and returns an
|
|
object containing callable wrappers.
|
|
|
|
When `definitions` is omitted, returns wrappers for all functions that have
|
|
already been resolved on the library.
|
|
|
|
### `library.getSymbol(name)`
|
|
|
|
* `name` {string}
|
|
* Returns: {bigint}
|
|
|
|
Resolves a symbol and returns its native address as a `bigint`.
|
|
|
|
### `library.getSymbols()`
|
|
|
|
* Returns: {Object}
|
|
|
|
Returns an object containing all previously resolved symbol addresses.
|
|
|
|
### `library.registerCallback([signature,] callback)`
|
|
|
|
* `signature` {Object}
|
|
* `callback` {Function}
|
|
* Returns: {bigint}
|
|
|
|
Creates a native callback pointer backed by a JavaScript function.
|
|
|
|
When `signature` is omitted, the callback uses a default `void ()` signature.
|
|
|
|
The return value is the callback pointer address as a `bigint`. It can be
|
|
passed to native functions expecting a callback pointer.
|
|
|
|
```cjs
|
|
const { DynamicLibrary, suffix } = require('node:ffi');
|
|
|
|
const lib = new DynamicLibrary(`./mylib.${suffix}`);
|
|
|
|
const callback = lib.registerCallback(
|
|
{ arguments: ['int32'], return: 'int32' },
|
|
(value) => value * 2,
|
|
);
|
|
```
|
|
|
|
Callbacks are subject to the following restrictions:
|
|
|
|
* They must be invoked on the same system thread where they were created.
|
|
* They must not throw exceptions.
|
|
* They must not return promises.
|
|
* They must return a value compatible with the declared return type.
|
|
* They must not call `library.close()` on their owning library while running.
|
|
* They must not unregister themselves while running.
|
|
|
|
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}
|
|
|
|
Releases a callback previously created with `library.registerCallback()`.
|
|
|
|
Calling `library.unregisterCallback(pointer)` for a callback that is currently
|
|
executing is unsupported and dangerous. The callback must return before it is
|
|
unregistered.
|
|
|
|
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}
|
|
|
|
Keeps the callback strongly referenced by JavaScript.
|
|
|
|
Throws `ERR_INVALID_ARG_VALUE` if the callback function has already been
|
|
garbage collected after a previous `library.unrefCallback(pointer)` call, since
|
|
a collected function cannot be referenced again.
|
|
|
|
### `library.unrefCallback(pointer)`
|
|
|
|
* `pointer` {bigint}
|
|
|
|
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.
|
|
|
|
Throws `ERR_INVALID_ARG_VALUE` if the callback function has already been
|
|
garbage collected.
|
|
|
|
## Calling native functions
|
|
|
|
Argument conversion depends on the declared FFI type.
|
|
|
|
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
|
|
JavaScript `number` values that match the declared type.
|
|
|
|
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
|
|
values.
|
|
|
|
For pointer-like arguments:
|
|
|
|
* `null` and `undefined` are passed as null pointers.
|
|
* `string` values are copied to temporary NUL-terminated UTF-8 strings for the
|
|
duration of the call.
|
|
* `Buffer`, typed arrays, and `DataView` instances pass a pointer to their
|
|
backing memory.
|
|
* `ArrayBuffer` passes a pointer to its backing memory.
|
|
* `bigint` values are passed as raw pointer addresses.
|
|
|
|
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)`
|
|
|
|
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`.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
```cjs
|
|
const {
|
|
getInt32,
|
|
setInt32,
|
|
} = require('node:ffi');
|
|
|
|
setInt32(ptr, 0, 42);
|
|
console.log(getInt32(ptr, 0));
|
|
```
|
|
|
|
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)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `pointer` {bigint}
|
|
* Returns: {string|null}
|
|
|
|
Reads a NUL-terminated UTF-8 string from native memory.
|
|
|
|
If `pointer` is `0n`, `null` is returned.
|
|
|
|
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.
|
|
|
|
```cjs
|
|
const { toString } = require('node:ffi');
|
|
|
|
const value = toString(ptr);
|
|
```
|
|
|
|
## `ffi.toBuffer(pointer, length[, copy])`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
* `copy` {boolean} When `false`, creates a zero-copy view. **Default:** `true`.
|
|
* Returns: {Buffer}
|
|
|
|
Creates a `Buffer` from native memory.
|
|
|
|
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.
|
|
|
|
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` remains valid for the entire lifetime of the returned `Buffer`.
|
|
* `length` stays within the allocated native region.
|
|
* no native code frees or repurposes that memory while JavaScript still uses
|
|
the `Buffer`.
|
|
* Memory protection is observed. For example, read-only memory pages must not
|
|
be written to.
|
|
|
|
If these guarantees are not met, reading or writing the `Buffer` can corrupt
|
|
memory or crash the process.
|
|
|
|
## `ffi.toArrayBuffer(pointer, length[, copy])`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
* `copy` {boolean} When `false`, creates a zero-copy view. **Default:** `true`.
|
|
* Returns: {ArrayBuffer}
|
|
|
|
Creates an `ArrayBuffer` from native memory.
|
|
|
|
When `copy` is `true`, the returned `ArrayBuffer` contains copied bytes.
|
|
When `copy` is `false`, the returned `ArrayBuffer` references the original
|
|
native memory directly.
|
|
|
|
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])`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `string` {string}
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
* `encoding` {string} **Default:** `'utf8'`.
|
|
|
|
Copies a JavaScript string into native memory and appends a trailing NUL
|
|
terminator.
|
|
|
|
`length` must be large enough to hold the full encoded string plus the trailing
|
|
NUL terminator. For UTF-16 and UCS-2 encodings, the trailing terminator uses
|
|
two zero bytes.
|
|
|
|
`pointer` must refer to writable native memory with at least `length` bytes of
|
|
available storage. This function does not allocate memory on its own.
|
|
|
|
`string` must be a JavaScript string. `encoding` must be a string.
|
|
|
|
## `ffi.exportBuffer(buffer, pointer, length)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `buffer` {Buffer}
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
|
|
Copies bytes from a `Buffer` into native memory.
|
|
|
|
`length` must be at least `buffer.length`.
|
|
|
|
`pointer` must refer to writable native memory with at least `length` bytes of
|
|
available storage. This function does not allocate memory on its own.
|
|
|
|
`buffer` must be a Node.js `Buffer`.
|
|
|
|
## `ffi.exportArrayBuffer(arrayBuffer, pointer, length)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `arrayBuffer` {ArrayBuffer}
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
|
|
Copies bytes from an `ArrayBuffer` into native memory.
|
|
|
|
`length` must be at least `arrayBuffer.byteLength`.
|
|
|
|
`pointer` must refer to writable native memory with at least `length` bytes of
|
|
available storage. This function does not allocate memory on its own.
|
|
|
|
## `ffi.exportArrayBufferView(arrayBufferView, pointer, length)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `arrayBufferView` {ArrayBufferView}
|
|
* `pointer` {bigint}
|
|
* `length` {number}
|
|
|
|
Copies bytes from an `ArrayBufferView` into native memory.
|
|
|
|
`length` must be at least `arrayBufferView.byteLength`.
|
|
|
|
`pointer` must refer to writable native memory with at least `length` bytes of
|
|
available storage. This function does not allocate memory on its own.
|
|
|
|
## `ffi.getRawPointer(source)`
|
|
|
|
<!-- YAML
|
|
added: v26.1.0
|
|
-->
|
|
|
|
* `source` {Buffer|ArrayBuffer|SharedArrayBuffer|ArrayBufferView}
|
|
* Returns: {bigint}
|
|
|
|
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.
|
|
|
|
## `ffi.getCurrentEventLoop()`
|
|
|
|
<!-- YAML
|
|
added: v26.6.0
|
|
-->
|
|
|
|
* Returns: {bigint}
|
|
|
|
Returns the address of the current thread's `uv_loop_t` as a `bigint`.
|
|
|
|
The returned address is for the current Node.js environment. In the main thread,
|
|
this is the main thread event loop. In a worker thread, this is that worker's
|
|
event loop.
|
|
|
|
This is unsafe and dangerous. The returned pointer is only valid for the lifetime
|
|
of the current environment. Using it after the environment exits, or from native
|
|
code that assumes a different thread or lifetime, can crash the process or
|
|
corrupt memory.
|
|
|
|
## Safety notes
|
|
|
|
The `node:ffi` module does not track pointer validity, memory ownership, or
|
|
native object lifetimes.
|
|
|
|
In particular:
|
|
|
|
* Do not read from or write to freed memory.
|
|
* Do not use zero-copy views after the native memory has been released.
|
|
* Do not declare incorrect signatures for native symbols.
|
|
* Do not unregister callbacks while native code may still call them.
|
|
* Do not call callback pointers after `library.close()` or
|
|
`library.unregisterCallback(pointer)`.
|
|
* Assume undefined callback behavior can crash the process, produce incorrect
|
|
output, or corrupt memory.
|
|
* Do not assume pointer return values imply ownership; whether the caller must
|
|
free the returned address depends entirely on the native 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.
|
|
|
|
[Permission Model]: permissions.md#permission-model
|
|
[`--allow-ffi`]: cli.md#--allow-ffi
|
|
[`ffi.toBuffer(pointer, length, copy)`]: #ffitobufferpointer-length-copy
|
|
[`library.functions`]: #libraryfunctions
|
|
[`using`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/using
|
|
[type names]: #type-names
|