Skip to content

Getting Started

zig-bind is a high-performance, zero-allocation JavaScript and TypeScript binding engine for Zig WebAssembly. It bypasses heavy object wrapper abstractions, allowing you to interface directly with WebAssembly linear memory using standard, flyweight-cached JavaScript TypedArrays.

Install the core registry package into your modern JavaScript runtime environment.

Terminal window
pnpm add zig-bind

Follow these steps to write your high-performance business logic, compile it using the CLI tool, and execute zero-copy calculations in JavaScript/TypeScript.

  1. Write Your Business Logic in Zig

    Create your native functionality. Ensure your exported functions use the pub export fn modifier so they can be discovered by the binding engine compiler.

    src/math.zig
    const std = @import("std");
    // Your high-performance business logic
    pub export fn add_vectors(a_ptr: [*]f32, b_ptr: [*]f32, c_ptr: [*]f32, len: usize) void {
    var i: usize = 0;
    while (i < len) : (i += 1) {
    c_ptr[i] = a_ptr[i] + b_ptr[i];
    }
    }
  2. Compile the WebAssembly Binary Use the zig-bind CLI tool to compile your code. For a simple standalone runtime environment without WASI requirements, pass the --standalone flag:

    Terminal window
    npx zig-bind build src/math.zig --out ./dist/math --standalone
  3. Initialize the Core Registry Load the compiled .wasm binary into your JavaScript runtime and feed it into the ZigBindRegistry manager:

    src/index.ts
    import fs from 'node:fs';
    import { ZigBindRegistry } from 'zig-bind';
    // Load the compiled WebAssembly binary
    const wasmBuffer = fs.readFileSync('./dist/math.wasm');
    const { instance } = await WebAssembly.instantiate(wasmBuffer, {});
    // Instantiate the high-speed registry agent
    export const registry = new ZigBindRegistry(instance);```
  4. Execute High-Speed, Zero-Copy Calculations Allocate vectors seamlessly using familiar syntax and run your compiled native operations with zero garbage collection churn:

    import { registry } from './index.js';
    // 1. Instantly allocate and fill memory spaces using native syntax
    const vecA = registry.alloc('f32', [10.0, 20.0, 30.0, 40.0]);
    const vecB = registry.alloc('f32', 4);
    vecB.set([1.5, 2.5, 3.5, 4.5]); // Pure native TypedArray method!
    const vecC = registry.alloc('f32', 4);
    // 2. Bind the function by its string name
    const add = registry.bind('add_vectors');
    // 3. Execute! Arity inferencing automatically passes trailing length arguments
    add(vecA, vecB, vecC);
    console.log(Array.from(vecC));
    // [11.5, 22.5, 33.5, 44.5]
    // 4. Wipe arena tokens when finished to reuse pointers on subsequent cycles
    registry.reset();