Skip to content

Commit 2c8aad8

Browse files
Docs Update for C++ [1/4] (#4118)
# Description of Changes In order to give reviewers a chance to finish in one session the docs are getting split up for the C++ update. This pass contains the following section updates: - Intro - Databases - How To # API and ABI breaking changes N/A # Expected complexity level and risk 1 - Just documentation additions # Testing - [x] Manually tested each block
1 parent c98088f commit 2c8aad8

File tree

9 files changed

+679
-5
lines changed

9 files changed

+679
-5
lines changed

docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ A SpacetimeDB **database** is an application that runs on a [host](#host).
1616

1717
A database exports [tables](#table), which store data, and [reducers](#reducer), which allow [clients](#client) to make requests.
1818

19-
A database's schema and business logic is specified by a piece of software called a **module**. Modules can be written in C#, Rust or TypeScript.
19+
A database's schema and business logic is specified by a piece of software called a **module**. Modules can be written in C#, C++, Rust or TypeScript.
2020

21-
(Technically, a SpacetimeDB module is a [WebAssembly module](https://developer.mozilla.org/en-US/docs/WebAssembly) or JavaScript bundle, that imports a specific low-level [WebAssembly ABI](/webassembly-abi) and exports a small number of special functions. However, the SpacetimeDB [server-side libraries](/databases) hide these low-level details. As a developer, writing a module is mostly like writing any other C# or Rust application, except for the fact that a [special CLI tool](https://spacetimedb.com/install) is used to deploy the application.)
21+
(Technically, a SpacetimeDB module is a [WebAssembly module](https://developer.mozilla.org/en-US/docs/WebAssembly) or JavaScript bundle, that imports a specific low-level [WebAssembly ABI](/webassembly-abi) and exports a small number of special functions. However, the SpacetimeDB [server-side libraries](/databases) hide these low-level details. As a developer, writing a module is mostly like writing any other application, except for the fact that a [special CLI tool](https://spacetimedb.com/install) is used to deploy the application.)
2222

2323
## Table
2424

@@ -71,6 +71,21 @@ pub struct Player {
7171
}
7272
```
7373

74+
</TabItem>
75+
<TabItem value="cpp" label="C++">
76+
77+
```cpp
78+
struct Player {
79+
uint64_t id;
80+
std::string name;
81+
uint32_t age;
82+
Identity user;
83+
};
84+
SPACETIMEDB_STRUCT(Player, id, name, age, user)
85+
SPACETIMEDB_TABLE(Player, players, Public)
86+
FIELD_PrimaryKey(players, id)
87+
```
88+
7489
</TabItem>
7590
7691
</Tabs>
@@ -147,6 +162,28 @@ fn main() {
147162
}
148163
```
149164

165+
</TabItem>
166+
<TabItem value="cpp" label="C++">
167+
168+
A reducer can be written in C++ like so:
169+
170+
```cpp
171+
SPACETIMEDB_REDUCER(set_player_name, ReducerContext ctx, uint64_t id, std::string name) {
172+
// ...
173+
return Ok();
174+
}
175+
```
176+
177+
And an Unreal C++ [client](#client) can call that reducer:
178+
179+
```cpp
180+
void AMyGameManager::UpdatePlayerName()
181+
{
182+
// ...setup code, then...
183+
Conn->Reducers->SetPlayerName(57, "Marceline");
184+
}
185+
```
186+
150187
</TabItem>
151188
</Tabs>
152189

@@ -242,6 +279,27 @@ While SpacetimeDB doesn't support nested transactions,
242279
a reducer can [schedule another reducer](https://docs.rs/spacetimedb/latest/spacetimedb/attr.reducer.html#scheduled-reducers) to run at an interval,
243280
or at a specific time.
244281

282+
</TabItem>
283+
<TabItem value="cpp" label="C++">
284+
285+
```cpp
286+
SPACETIMEDB_REDUCER(world, ReducerContext ctx) {
287+
clear_all_tables(ctx);
288+
return Ok();
289+
}
290+
291+
SPACETIMEDB_REDUCER(hello, ReducerContext ctx) {
292+
if (world(ctx).is_err()) {
293+
other_changes(ctx);
294+
}
295+
return Ok();
296+
}
297+
```
298+
299+
While SpacetimeDB doesn't support nested transactions,
300+
a reducer can [schedule another reducer](/tables/schedule-tables) to run at an interval,
301+
or at a specific time.
302+
245303
</TabItem>
246304
</Tabs>
247305
@@ -361,7 +419,21 @@ fn main() {
361419
```
362420

363421
</TabItem>
364-
<TabItem value="cpp" label="Unreal C++">
422+
<TabItem value="cpp" label="C++">
423+
424+
A procedure can be defined in a C++ module:
425+
426+
```cpp
427+
SPACETIMEDB_PROCEDURE(std::string, make_request, ProcedureContext ctx) {
428+
// ...
429+
return std::string{"result"};
430+
}
431+
```
432+
433+
Use the other tabs (TypeScript/C#/Rust/Unreal C++/Blueprint) for client call examples.
434+
435+
</TabItem>
436+
<TabItem value="cpp-unreal" label="Unreal C++">
365437
366438
An Unreal C++ [client](#client) can call a procedure defined by a Rust or TypeScript module:
367439
@@ -455,6 +527,17 @@ fn my_player(ctx: &spacetimedb::ViewContext) -> Option<Player> {
455527
}
456528
```
457529

530+
</TabItem>
531+
<TabItem value="cpp" label="C++">
532+
533+
A view can be written in C++ like so:
534+
535+
```cpp
536+
SPACETIMEDB_VIEW(std::optional<Player>, my_player, Public, ViewContext ctx) {
537+
return ctx.db[player_identity].find(ctx.sender);
538+
}
539+
```
540+
458541
</TabItem>
459542
</Tabs>
460543
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
title: C++ Quickstart
3+
sidebar_label: C++
4+
slug: /quickstarts/c-plus-plus
5+
hide_table_of_contents: true
6+
---
7+
8+
import { InstallCardLink } from "@site/src/components/InstallCardLink";
9+
import { StepByStep, Step, StepText, StepCode } from "@site/src/components/Steps";
10+
11+
Get a SpacetimeDB C++ app running in under 5 minutes.
12+
13+
## Prerequisites
14+
15+
- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
16+
- [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) 4.0.21+ installed
17+
- CMake 3.20+ and a make/ninja backend
18+
- C++20 toolchain (host) — build targets WASM via Emscripten
19+
20+
After installing the SDK, run the appropriate `emsdk_env` script (PowerShell or Bash) so `emcc` and the CMake toolchain file are available on `PATH`.
21+
22+
<InstallCardLink />
23+
24+
---
25+
26+
<StepByStep>
27+
<Step title="Install Emscripten">
28+
<StepText>
29+
Use the official SDK (see [Emscripten downloads](https://emscripten.org/docs/getting_started/downloads.html)) and activate the environment so `emcc` and the CMake toolchain file are on PATH. We recommend Emscripten 4.0.21+.
30+
</StepText>
31+
<StepCode>
32+
```bash
33+
# From your emsdk directory (after downloading/cloning)
34+
# Windows PowerShell
35+
./emsdk install 4.0.21
36+
./emsdk activate 4.0.21
37+
./emsdk_env.ps1
38+
39+
# macOS/Linux
40+
./emsdk install 4.0.21
41+
./emsdk activate 4.0.21
42+
source ./emsdk_env.sh
43+
```
44+
</StepCode>
45+
</Step>
46+
47+
<Step title="Create your project">
48+
<StepText>
49+
Use the CLI-managed workflow with `spacetime build`, which wraps CMake + `emcc` for you, starts the local server, builds/publishes your module, and generates client bindings.
50+
</StepText>
51+
<StepCode>
52+
```bash
53+
spacetime dev --template basic-cpp my-spacetime-app
54+
```
55+
</StepCode>
56+
<StepText>
57+
Need manual control? You can still drive CMake+emcc directly (see `spacetimedb/CMakeLists.txt`), but the recommended path is `spacetime build`/`spacetime dev`.
58+
</StepText>
59+
</Step>
60+
61+
<Step title="Explore the project structure">
62+
<StepText>
63+
Server code lives in the `spacetimedb` folder; the template uses CMake and the SpacetimeDB C++ SDK.
64+
</StepText>
65+
<StepCode>
66+
```
67+
my-spacetime-app/
68+
├── spacetimedb/ # Your C++ module
69+
│ ├── CMakeLists.txt
70+
│ └── src/
71+
│ └── lib.cpp # Server-side logic
72+
└── client/ # Client bindings (generated by spacetime dev)
73+
```
74+
</StepCode>
75+
</Step>
76+
77+
<Step title="Understand tables and reducers">
78+
<StepText>
79+
The template includes a `Person` table and two reducers: `add` to insert, `say_hello` to iterate and log.
80+
</StepText>
81+
<StepCode>
82+
```cpp
83+
#include "spacetimedb.h"
84+
using namespace SpacetimeDB;
85+
86+
struct Person { std::string name; };
87+
SPACETIMEDB_STRUCT(Person, name)
88+
SPACETIMEDB_TABLE(Person, person, Public)
89+
90+
SPACETIMEDB_REDUCER(add, ReducerContext ctx, std::string name) {
91+
ctx.db[person].insert(Person{name});
92+
return Ok();
93+
}
94+
95+
SPACETIMEDB_REDUCER(say_hello, ReducerContext ctx) {
96+
for (const auto& person : ctx.db[person]) {
97+
LOG_INFO("Hello, " + person.name + "!");
98+
}
99+
LOG_INFO("Hello, World!");
100+
return Ok();
101+
}
102+
```
103+
</StepCode>
104+
</Step>
105+
106+
<Step title="Test with the CLI">
107+
<StepText>
108+
Call reducers and inspect data right from the CLI.
109+
</StepText>
110+
<StepCode>
111+
```bash
112+
# Insert a person
113+
spacetime call <database-name> add Alice
114+
115+
# Query the person table
116+
spacetime sql <database-name> "SELECT * FROM person"
117+
118+
# Call say_hello to greet everyone
119+
spacetime call <database-name> say_hello
120+
121+
# View the module logs
122+
spacetime logs <database-name>
123+
```
124+
</StepCode>
125+
</Step>
126+
</StepByStep>
127+
128+
## Notes
129+
130+
- To use a local SDK clone instead of the fetched archive, set `SPACETIMEDB_CPP_SDK_DIR` before running `spacetime dev`/`spacetime build`.
131+
- The template builds to WebAssembly with exceptions disabled (`-fno-exceptions`).
132+
- If `emcc` is not found, re-run the appropriate `emsdk_env` script to populate environment variables.

docs/docs/00200-core-concepts/00100-databases.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ slug: /databases
77
import Tabs from '@theme/Tabs';
88
import TabItem from '@theme/TabItem';
99

10-
A **module** is a collection of functions and schema definitions, which can be written in TypeScript, C# or Rust. Modules define the structure of your database and the server-side logic that processes and handles client requests.
10+
A **module** is a collection of functions and schema definitions, which can be written in TypeScript, C#, Rust, or C++. Modules define the structure of your database and the server-side logic that processes and handles client requests.
1111

1212
A **database** is a running instance of a module. While a module is the code you write (schema and reducers), a database is the actual deployed entity running on a SpacetimeDB **host** with stored data and active connections.
1313

1414
## Module vs Database
1515

1616
Understanding this distinction is important:
1717

18-
- A **module** is the code you write; it defines your schema (tables) and business logic (reducers, procedures, and views). Modules are compiled and deployed to SpacetimeDB. Rust and C# modules compile to WebAssembly, while TypeScript modules run on V8.
18+
- A **module** is the code you write; it defines your schema (tables) and business logic (reducers, procedures, and views). Modules are compiled and deployed to SpacetimeDB. Rust, C#, and C++ modules compile to WebAssembly, while TypeScript modules run on V8.
1919
- A **database** is a *running instance* of a module; it has the module's schema and logic, plus actual stored data.
2020

2121
You can deploy the same module to multiple databases (e.g. separate environments for testing, staging, production), each with its own independent data. When you update your module code and re-publish, SpacetimeDB will update the database's schema/logic — the existing data remains (though for complicated schema changes you may need to handle migrations carefully).
@@ -57,6 +57,13 @@ Rust is fully supported for server modules. Rust is a great choice for performan
5757
- The Rust Module SDK docs are [hosted on docs.rs](https://docs.rs/spacetimedb/latest/spacetimedb/).
5858
- [Rust Quickstart Guide](/quickstarts/rust)
5959

60+
</TabItem>
61+
<TabItem value="cpp" label="C++">
62+
63+
C++ is fully supported for server modules. C++ is an excellent choice for developers working with Unreal Engine or those who prefer to stay in the C++ ecosystem.
64+
65+
- [C++ Quickstart Guide](/quickstarts/c-plus-plus)
66+
6067
</TabItem>
6168
</Tabs>
6269

docs/docs/00200-core-concepts/00100-databases/00100-transactions-atomicity.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,42 @@ pub fn child_reducer(ctx: &ReducerContext) -> Result<(), String> {
152152
}
153153
```
154154

155+
</TabItem>
156+
<TabItem value="cpp" label="C++">
157+
158+
```cpp
159+
using namespace SpacetimeDB;
160+
161+
// Forward declare child reducer to allow calling it before its definition
162+
ReducerResult child_reducer(ReducerContext&, bool some_condition);
163+
164+
SPACETIMEDB_REDUCER(parent_reducer, ReducerContext ctx, bool some_condition) {
165+
ctx.db[table_a].insert(RowA{ /* ... */ });
166+
167+
// This runs in the SAME transaction
168+
ReducerResult result = child_reducer(ctx, some_condition);
169+
if (result.is_err()) {
170+
return result;
171+
}
172+
173+
ctx.db[table_b].insert(RowB{ /* ... */ });
174+
175+
// All changes from both parent and child commit together
176+
return Ok();
177+
}
178+
179+
SPACETIMEDB_REDUCER(child_reducer, ReducerContext ctx, bool some_condition) {
180+
ctx.db[table_c].insert(RowC{ /* ... */ });
181+
182+
// If this returns Err, the parent's changes also roll back
183+
if (some_condition) {
184+
return Err("Child failed");
185+
}
186+
187+
return Ok();
188+
}
189+
```
190+
155191
</TabItem>
156192
</Tabs>
157193

docs/docs/00200-core-concepts/00100-databases/00200-spacetime-dev.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Choose from several built-in templates:
6767
- `basic-ts` - Basic TypeScript client and server stubs
6868
- `basic-cs` - Basic C# client and server stubs
6969
- `basic-rs` - Basic Rust client and server stubs
70+
- `basic-cpp` - Basic C++ server stubs
7071
- `react-ts` - React web app with TypeScript server
7172
- `chat-console-rs` - Complete Rust chat implementation
7273
- `chat-console-cs` - Complete C# chat implementation
@@ -81,6 +82,7 @@ Creates a server module only, without any client code. You'll choose your server
8182
- **TypeScript** - Server module in TypeScript
8283
- **Rust** - Server module in Rust
8384
- **C#** - Server module in C#
85+
- **C++** - Server module in C++
8486

8587
The server code will be created in a `spacetimedb/` subdirectory within your project.
8688

@@ -147,6 +149,18 @@ my-project/
147149
└── README.md
148150
```
149151

152+
</TabItem>
153+
<TabItem value="cpp" label="C++">
154+
155+
```text
156+
my-project/
157+
├── spacetimedb/ # Server module code (C++)
158+
│ ├── CMakeLists.txt
159+
│ └── src/
160+
│ └── lib.cpp
161+
└── README.md
162+
```
163+
150164
</TabItem>
151165
</Tabs>
152166

@@ -198,6 +212,20 @@ This creates a new Rust project with:
198212
- A `src/lib.rs` with a sample module
199213
- Sample table and reducer definitions
200214

215+
</TabItem>
216+
<TabItem value="cpp" label="C++">
217+
218+
```bash
219+
spacetime init --lang cpp --project-path ./my-project my-project
220+
cd my-project
221+
```
222+
223+
This creates a new C++ project with:
224+
225+
- A `CMakeLists.txt` configured for SpacetimeDB
226+
- A `src/lib.cpp` with a sample module
227+
- Sample table and reducer definitions
228+
201229
</TabItem>
202230
</Tabs>
203231

0 commit comments

Comments
 (0)