Native FFI

js/native-ffi.md

fino:ffi loads native libraries and binds C ABI functions. It is a sharp runtime extension surface for advanced applications and built-in modules that need system calls, native codecs, crypto libraries, database clients, or platform APIs before a higher-level fino:* wrapper exists.

Prefer public Fino modules when they cover the job. A wrong FFI signature, pointer lifetime, callback lifetime, struct layout, or ownership assumption can crash the process.

Load Symbols

import { dlopen } from 'fino:ffi';

const libc = dlopen(null, {
  getpid: { parameters: [], result: 'i32' },
});

console.log(libc.symbols.getpid());

path may be null to resolve symbols from the current process. The symbol map declares parameter and result descriptors used by the native binding layer.

Work With Pointers

Pointer helpers read, write, copy, offset, and view native memory:

import { Pointer } from 'fino:ffi';

const bytes = new Uint8Array(8);
const ptr = Pointer.of(bytes);
Pointer.writeU32(ptr, 0, 42);
console.log(Pointer.readU32(ptr, 0));

Buffers passed to native code must remain alive for as long as native code may read them. Native memory viewed through Pointer.view() must outlive the returned buffer unless onRelease owns cleanup.

Callbacks And Blocking Work

FfiCallback creates native-callable JS callbacks. Retain the callback object for as long as native code may call it; dropping it while native code still has the function pointer is unsafe.

Mark long-running symbols async or nonblocking so they run on the native blocking pool instead of stalling the JS event loop.

The full fino:ffi surface — types, struct layout, callbacks, and pointer helpers — is documented in the generated API reference.