Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Embedding via FFI

baedeker-ffi exposes the engine as a C ABI (staticlib + cdylib) for host embedding from C, C++, Swift, Kotlin, or any language with C interop. A build.rs runs cbindgen to generate baedeker.h from the Rust source.

Handle model

The FFI is handle-based to keep ownership on the Rust side:

HandleOwns
BaedekerModulean Arc<RegModule> (decoded + validated + lowered)
BaedekerInstancea Store + module reference

Compile a module once, instantiate it many times. Every FFI entry returns a status enum; on failure a thread-local last-error string is available via baedeker_last_error.

A C end-to-end run

#include "baedeker.h"

BaedekerModule *mod = baedeker_module_compile(wasm_bytes, len);
BaedekerInstance *inst = baedeker_instance_new(mod);

BaedekerValue args[2] = {{.tag = BAEDeker_I32, .i32 = 20},
                         {.tag = BAEDeker_I32, .i32 = 22}};
BaedekerValue out[1];
size_t n = baedeker_instance_call(inst, "add", args, 2, out, 1);
assert(out[0].i32 == 42);

(See crates/baedeker-ffi/tests/smoke.c for the full, compiling version.)

Memory, fuel, and sizes

The FFI exposes memory read/write (baedeker_instance_memory_data/read/write), fuel (baedeker_instance_set_fuel), and host-function registration. Size parameters are uint64_t from day one, anticipating the memory64 proposal.

The value union

BaedekerValue is an extensible tagged union:

typedef enum { BAEDeker_I32, BAEDeker_I64, BAEDeker_F32,
               BAEDeker_F64, BAEDeker_V128 } BaedekerValueTag;

typedef struct {
    BaedekerValueTag tag;   // a plain uint8_t — see the ABI note below
    union { int32_t i32; int64_t i64; float f32;
            double f64; uint8_t v128[16]; } u;
} BaedekerValue;

The tag is a plain uint8_t, not a C enum: pre-C23 C enums are int-sized (four bytes), which would read three bytes of undefined padding against Rust’s one-byte discriminant. cbindgen is post-processed to emit the tag as a typed enum on both branches.