Node.js (native)
Using unffi with native node:ffi (Node ≥26.3.0) — no build step, built-in FFI.
Node ≥26.3.0 ships node:ffi as a stable built-in module. unffi detects it automatically — no schema changes needed when upgrading from koffi.
# Node ≥26.3.0 — stable, no flag needed
node --experimental-ffi main.mjsNative node:ffi is stable in Node 26.3.0+. Earlier 26.x versions require --experimental-ffi and may have incomplete ABI support — unffi falls back to koffi in that case.
Quick start
import { , } from 'unffi'
const = await ('./libmath.dylib', {
: { : [., .], : . },
: { : [.], : . },
})
const sum = ..(3, 4)const root = ..(2.0)Feature parity
All core unffi features work identically with the native backend:
- Primitives:
t.i8–t.i64,t.u8–t.u64,t.f32,t.f64 - Bool:
t.bool(returned asboolean) - CString:
t.cstring(auto-encodes input string, decodes output) - Buffer:
t.bufferfor zero-copy TypedArray arguments - Callbacks:
t.fn(args, returns)for function pointers - Async:
async: truefor non-blocking FFI
Type compatibility
node:ffi always returns bigint for i64/u64. koffi returns number for small values — if you're migrating, use Number() for cross-backend compatibility:
const val = Number(lib.symbols.add_i64(1n, 2n)) // 3t namespace
The t object on Node exports the same KoffiT interface for both backends, so your schema works unchanged whether native node:ffi or koffi is active.
Koffi features
Some koffi-specific features (t.koffi.struct, t.koffi.out, opaque handles, wide strings) are only available via the koffi adapter. See the koffi runtime docs for details.