Files
Jason Larabie 52b6c66fa1 Add C++ Bindings (#3544)
# Description of Changes

This adds C++ server bindings (/crate/bindings-cpp) to allow writing C++
20 modules.

- Emscripten WASM build system integration with CMake
- Macro-based code generation (SPACETIMEDB_TABLE, SPACETIMEDB_REDUCER,
etc)
- All SpacetimeDB types supported (primitives, Timestamp, Identity,
Uuid, etc)
- Product types via SPACETIMEDB_STRUCT
- Sum types via SPACETIMEDB_ENUM
- Constraints marked with FIELD* macros

# API and ABI breaking changes

None

# Expected complexity level and risk

2 - Doesn't heavily impact any other areas but is complex macro C++
structure to support a similar developer experience, did have a small
impact on init command

# Testing

- [x] modules/module-test-cpp - heavily tested every reducer
- [x] modules/benchmarks-cpp - tested through the standalone (~6x faster
than C#, ~6x slower than Rust)
- [x] modules/sdk-test-cpp
- [x] modules/sdk-test-procedure-cpp
- [x] modules/sdk-test-view-cpp  
- [x] Wrote several test modules myself
- [x] Quickstart smoketest [Currently in progress]
- [ ] Write Blackholio C++ server module

---------

Signed-off-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
2026-02-07 04:26:45 +00:00

3.4 KiB

SpacetimeDB C++ Module Library Internal API

This directory contains the internal implementation of the SpacetimeDB C++ Module Library, matching the design of the C# bindings.

Overview

The Internal API provides:

  • Module Definition Management: Automatic generation of module definitions using autogenerated types
  • Type Registration: Type-safe registration system for tables and reducers
  • FFI Wrappers: Safe wrappers around the SpacetimeDB ABI
  • Table Operations: Type-safe CRUD operations on tables
  • Reducer System: Framework for implementing reducers with proper serialization

Directory Structure

  • autogen/ - Autogenerated types from Rust definitions (RawModuleDefV9, RawTableDefV9, etc.)

  • Module.h/cpp - Main module management and registration

  • FFI.h/cpp - Foreign Function Interface definitions

Key Components

1. Module Registration

The Module class is a singleton that manages:

  • Table registration
  • Reducer registration
  • Type registration
  • Module description generation
  • Reducer invocation

2. Autogenerated Types

All module definition types are generated from the Rust codebase:

  • RawModuleDefV9 - Main module definition
  • RawTableDefV9 - Table definitions
  • RawReducerDefV9 - Reducer definitions
  • TableAccess, TableType, etc. - Enums and supporting types

3. Table Implementation

Tables are implemented using the SPACETIMEDB_TABLE macro system:

  1. Define row types with field registration using SPACETIMEDB_MODULE_STRUCT (modules) or SPACETIMEDB_STRUCT (clients)
  2. Register tables with SPACETIMEDB_TABLE(Type, "name", Access, ...constraints)
  3. Use ctx.db.table<T>("name") for table operations (insert, delete)
  4. Tables are automatically registered during module initialization via __preinit__ functions

4. Reducer Implementation

Reducers are implemented using unified macro system:

  1. SPACETIMEDB_REDUCER(name, ReducerContext ctx, ...params) - User-defined reducers
  2. SPACETIMEDB_INIT(name, ReducerContext ctx) - Module initialization
  3. SPACETIMEDB_CLIENT_CONNECTED(name, ReducerContext ctx) - Client connection handler
  4. SPACETIMEDB_CLIENT_DISCONNECTED(name, ReducerContext ctx) - Client disconnection handler
  5. The macros handle serialization, registration, and ABI integration automatically

Usage Example

// Define row type with field registration
struct Person {
    uint32_t id;
    std::string name;
    uint8_t age;
};
SPACETIMEDB_MODULE_STRUCT(Person, id, name, age);

// Define table with constraints
SPACETIMEDB_TABLE(Person, "people", Public,
    PrimaryKeyAutoInc(id),
    Index(name)
);

// Define reducer with ReducerContext
SPACETIMEDB_REDUCER(add_person, ReducerContext ctx, std::string name, uint8_t age) {
    // Access table and insert record
    Person person{0, name, age}; // id will be auto-generated
    ctx.db.table<Person>("people").insert(person);
    LOG_INFO("Added person: " + name);
}

// Lifecycle reducers
SPACETIMEDB_INIT(init, ReducerContext ctx) {
    LOG_INFO("Module initialized!");
    return Ok();
}

SPACETIMEDB_CLIENT_CONNECTED(on_connect, ReducerContext ctx) {
    LOG_INFO("Client connected!");
    return Ok();
}

Migration from Old API

See MIGRATION_GUIDE.md for detailed steps on migrating from the manual module definition approach to this new Internal API.

Future Improvements

  • Automatic BSATN serialization generation
  • Macro-based table/reducer definitions
  • Query builder API
  • Index management