🦊 ABI Reference β€” Functions and Usage Contract

This document describes the public C-ABI exposed by Vulfram and the contract expected from hosts and language bindings.

It is intended for:

  • Binding authors (N-API, mlua, PyO3, etc.)
  • Advanced users integrating Vulfram at a low level

1. Global Conventions

1.1 Return Type: `VulframResult (u32)`

All vulfram_* functions return a u32 status code:

  • 0 β†’ success (VULFRAM_SUCCESS)
  • non-zero β†’ error (VulframResult enum)

Bindings should translate errors into the host language (throw, return error, etc.).

1.2 Threading and Reentrancy

  • All ABI calls are main-thread only.
  • Do not call Vulfram from multiple threads at the same time.

1.3 WASM Mode Differences (Browser)

  • Browser-only: vulfram_init() fails if window is not available.
  • Canvas required: cmd-window-create needs canvasId (DOM canvas).
  • Window APIs are limited: some window commands (position, size, decorations, icon, state) are not supported in WASM and return errors.
  • Event loop is the browser: input events come from DOM listeners and are delivered via vulfram_receive_events.

1.4 Serialization Format

All structured data crossing the ABI uses MessagePack:

  • Commands (vulfram_send_queue)
  • Responses (vulfram_receive_queue)
  • Events (vulfram_receive_events)
  • Profiling (vulfram_get_profiling)

1.5 Output Buffers (`out_ptr`, `out_length`)

Several functions return data through pointer-out parameters:

c
u32 vulfram_xxx(uint8_t** out_ptr, size_t* out_length);

Contract:

  1. The core allocates a buffer and returns pointer + length.
  2. The binding copies it into host memory.
  3. The binding frees the core buffer using the provided mechanism.

Notes on current transports:

  • WASM: the JS wrapper calls result.free() after copying the data.
  • N-API: the core buffer is converted into a Node.js Buffer (Rust takes back ownership).
  • Bun FFI: data is copied into a Buffer, but there is currently no explicit free call exposed in the FFI surface (add one if you need to avoid leaks).

The game/app code never touches raw pointers directly.


2. Function List

2.1 Initialization and Shutdown

c
u32 vulfram_init(void);
u32 vulfram_dispose(void);
  • vulfram_init() initializes global state and must be called once.
  • vulfram_dispose() frees resources and ends the session.

2.2 Command Queue (Host β†’ Core)

c
u32 vulfram_send_queue(const uint8_t* buffer, size_t length);
  • buffer is a MessagePack batch of commands.
  • Commands are processed on the next vulfram_tick.

2.3 Response Queue (Core β†’ Host)

c
u32 vulfram_receive_queue(uint8_t** out_ptr, size_t* out_length);
  • Returns a MessagePack batch of responses (ACKs, errors, info).
  • out_length == 0 means β€œno responses available”.
  • Calling this consumes the internal response queue.

2.4 Event Queue (Input / Window)

c
u32 vulfram_receive_events(uint8_t** out_ptr, size_t* out_length);
  • Returns a MessagePack batch of input and window events.
  • Same ownership rules as vulfram_receive_queue.

2.5 Upload Raw Blobs

c
u32 vulfram_upload_buffer(uint64_t id,
                          uint32_t type,
                          const uint8_t* buffer,
                          size_t length);
  • Uploads heavy data (meshes, textures, etc.) into the core.
  • id is the host-chosen BufferId referenced by later Create* commands.
  • Uploads are one-shot: consumed and then freed.

2.6 Advance the Core

c
u32 vulfram_tick(uint64_t time, uint32_t delta_time);

This drives the entire engine for one frame:

  • Processes queued commands
  • Updates internal state
  • Collects input/window events
  • Executes rendering
  • Prepares responses/events/profiling for the host

2.7 Profiling Data

c
u32 vulfram_get_profiling(uint8_t** out_ptr, size_t* out_length);

Returns a MessagePack blob with timing and counters for the last frame.


A safe and common order per frame:

  1. Update host logic
  2. Upload blobs (optional)
  3. vulfram_send_queue
  4. vulfram_tick
  5. vulfram_receive_queue
  6. vulfram_receive_events
  7. vulfram_get_profiling (optional)

4. Error Handling Guidelines

  • Any non-zero return should be surfaced as an error to the host.
  • For details, poll vulfram_receive_queue for structured error responses.

5. Common Binding Pitfalls

  • Skipping copy/free of output buffers β†’ memory leaks.
  • Calling from multiple threads β†’ undefined behavior.
  • Reusing BufferIds without cleanup β†’ upload conflicts.
Documentation Vulfram Core