World
The world owns entity records, component storage, query state, systems, resources, and runtime metadata.
ecs_init() / ecs_fini() Entity Component System
SIECS groups entities by component set, stores components in contiguous columns, and runs systems over cached table queries.
Each concept has a distinct role in storage or execution. Together they define how data moves through the world.
The world owns entity records, component storage, query state, systems, resources, and runtime metadata.
ecs_init() / ecs_fini() An entity is a handle associated with a component set. Adding or removing components changes the entity's archetype.
ecs_entity_t / ecs_new() Entities with the same component set share a table. Every data component occupies a contiguous column inside that table.
[Position] [Velocity] [Entity] A query describes required access and caches every archetype table that satisfies its terms.
ecs_query({ .terms = { ... } })
A system binds a persistent query to a callback and an execution phase.
The world runs enabled systems through ecs_progress().
query + callback + phase Query matching and data iteration are separate steps. The query stores compatible tables, while the iterator exposes their component columns.
Value updates stay in place. Writing an existing component updates its current archetype column.
Composition changes move entities. Adding or removing a component transfers the entity to the matching archetype.
Tags only affect matching. A zero-sized component changes the archetype identity without allocating a data column.
C exposes query terms and batch iterators explicitly. C++ derives component access from callback parameter types and calls the same runtime.
Compare the APIsecs_query_id_t moving = ecs_query({
.terms = {
ecs_inout(Position),
ecs_in(Velocity),
},
});
ecs_iter_t it = ecs_query_iter(moving);
while (ecs_iter_next(&it)) {
Position *positions = ecs_field(&it, 0);
const Velocity *velocities = ecs_field(&it, 1);
for (uint32_t i = 0; i < it.count; i++) {
positions[i].x += velocities[i].x;
positions[i].y += velocities[i].y;
}
} ecs::query()
.each([](
Position &position,
const Velocity &velocity
) {
position.x += velocity.x;
position.y += velocity.y;
}); Storage, execution, relationships, and metadata use the same world model. Tools can inspect the same information that application code uses.
Archetype tables hold component columns. Cached queries select tables, iterators expose batches, and systems schedule callbacks by phase.
query / iterator / system / phase Resources store world-level values. Observers react to events. Relations express hierarchy, entity targets, and inheritance. Modules group related registrations behind one import.
resource / observer / relation / module Reflection describes component fields. JSON support serializes reflected values, and the optional REST explorer exposes schemas and entities to external tools.
reflection / JSON / REST explorer
Copy siecs.h and siecs.c from the standalone
distribution. C and C++ applications include the same public header and link
the same C runtime.
cc -std=c23 -I. main.c siecs.c -pthread -o my_app Each archetype table represents one exact component set. Data components occupy separate contiguous columns, while tags contribute only to the table identity.
A persistent query stores the archetype tables that satisfy its terms. An iterator walks that table set and resolves the requested columns.
A system owns a persistent query, a callback, and an execution phase.
ecs_progress() evaluates enabled systems in phase order.
Reflection records component schemas, JSON serializes reflected values, and the optional REST explorer provides schema and entity endpoints.
Register components, create an entity, define a system, and progress the runtime.