Node.js module

node:ffi

  • enum types

    • readonly path: string

      The path used to load the library.

    • readonly symbols: {
      __index[
      symbol: string
      ]: bigint;
      }

      An object containing previously resolved symbol addresses as bigint values.

    • 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.

    • close(): void;

      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.

      import { DynamicLibrary } from 'node:ffi';
      
      {
        using lib = new DynamicLibrary('./mylib.so');
        // 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.

    • name: string,
      signature: T

      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.

      const { DynamicLibrary } = require('node:ffi');
      
      const lib = new DynamicLibrary('./mylib.so');
      const add = lib.getFunction('add_i32', {
        arguments: ['i32', 'i32'],
        return: 'i32',
      });
      
      console.log(add(20, 22));
      console.log(add.pointer);
      
    • getFunctions(): {
      __index[
      symbol: string
      ]: WrappedFunction<any, any[]>;
      }
      ;

      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.

      definitions: T

      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.

    • name: string
      ): bigint;

      Resolves a symbol and returns its native address as a bigint.

    • getSymbols(): Record<string, bigint>;

      Returns an object containing all previously resolved symbol addresses.

    • pointer: bigint
      ): void;

      Keeps the callback strongly referenced by JavaScript.

    • callback: () => void
      ): 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.

      const { DynamicLibrary } = require('node:ffi');
      
      const lib = new DynamicLibrary('./mylib.so');
      
      const callback = lib.registerCallback(
        { arguments: ['i32'], return: 'i32' },
        (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.

      signature: T,
      ): 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.

      const { DynamicLibrary } = require('node:ffi');
      
      const lib = new DynamicLibrary('./mylib.so');
      
      const callback = lib.registerCallback(
        { arguments: ['i32'], return: 'i32' },
        (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.

    • pointer: bigint
      ): void;

      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.

    • pointer: bigint
      ): void;

      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.

  • const suffix: 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:

    const { suffix } = require('node:ffi');
    
    const path = `libsqlite3.${suffix}`;
    
  • function dlclose(
    ): void;

    Closes a dynamic library.

    This is equivalent to calling handle.close().

  • function dlopen<T extends FunctionDefinitions = {}>(
    path: null | string,
    definitions?: T

    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 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: { arguments: ['i32', 'i32'], return: '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: { arguments: ['i32', 'i32'], return: 'i32' },
      string_length: { arguments: ['pointer'], return: 'u64' },
    });
    
    console.log(functions.add_i32(20, 22));
    
    @param path

    Path to a dynamic library, or null to resolve symbols from the current process image.

    @param definitions

    Symbol definitions to resolve immediately.

  • function dlsym(
    symbol: string
    ): bigint;

    Resolves a symbol address from a loaded library.

    This is equivalent to calling handle.getSymbol(symbol).

  • arrayBuffer: ArrayBuffer,
    pointer: bigint,
    length: number
    ): void;

    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.

  • arrayBufferView: ArrayBufferView,
    pointer: bigint,
    length: number
    ): void;

    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.

  • function exportBuffer(
    buffer: Buffer,
    pointer: bigint,
    length: number
    ): void;

    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.

  • function exportString(
    string: string,
    pointer: bigint,
    length: number,
    encoding?: BufferEncoding
    ): void;

    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.

    @param encoding

    Default: 'utf8'.

  • function getFloat32(
    pointer: bigint,
    offset?: number
    ): number;
  • function getFloat64(
    pointer: bigint,
    offset?: number
    ): number;
  • function getInt16(
    pointer: bigint,
    offset?: number
    ): number;
  • function getInt32(
    pointer: bigint,
    offset?: number
    ): number;
  • function getInt64(
    pointer: bigint,
    offset?: number
    ): bigint;
  • function getInt8(
    pointer: bigint,
    offset?: number
    ): number;
  • function getRawPointer(
    source: ArrayBuffer | ArrayBufferView<ArrayBufferLike>
    ): 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.

  • function getUint16(
    pointer: bigint,
    offset?: number
    ): number;
  • function getUint32(
    pointer: bigint,
    offset?: number
    ): number;
  • function getUint64(
    pointer: bigint,
    offset?: number
    ): bigint;
  • function getUint8(
    pointer: bigint,
    offset?: number
    ): number;
  • function setFloat32(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setFloat64(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setInt16(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setInt32(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setInt64(
    pointer: bigint,
    offset: number,
    value: number | bigint
    ): void;
  • function setInt8(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setUint16(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setUint32(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function setUint64(
    pointer: bigint,
    offset: number,
    value: number | bigint
    ): void;
  • function setUint8(
    pointer: bigint,
    offset: number,
    value: number
    ): void;
  • function toArrayBuffer(
    pointer: bigint,
    length: number,
    copy?: boolean

    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.

    @param copy

    When false, creates a zero-copy view. Default: true.

  • function toBuffer(
    pointer: bigint,
    length: number,
    copy?: boolean
    ): NonSharedBuffer;

    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.

    @param copy

    When false, creates a zero-copy view. Default: true.

  • function toString(
    pointer: bigint
    ): null | string;

    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.

Type definitions