The C ABI
The model from any language
Core is a C++ and Python library, and it also exposes a flat C ABI so the document model can be driven from any language with a C foreign-function interface: Rust, Swift, Go, Lua, a game engine's scripting host. The C surface mirrors the C++ API: an opaque document handle, functions to shape and read it, and the native serialization.
#include "kinogaki/C.h"
#include <stdio.h>
kinogaki_document_t* s = kinogaki_document_new();
char final[256]; /* add_element writes back the final path */
kinogaki_document_add_element(s, "/world", "group", final, sizeof final);
kinogaki_document_add_element(s, "/world/mat", "material", final, sizeof final);
float rgb[3] = {0.8f, 0.1f, 0.1f};
kinogaki_element_set_float3(s, "/world/mat", "out", rgb);
kinogaki_document_add_element(s, "/world/ball", "object", final, sizeof final);
kinogaki_element_set_float(s, "/world/ball", "radius", 1.5f);
kinogaki_document_connect(s, "/world/mat.out", "/world/ball.albedo"); /* source output → target input */
size_t n = 0;
char* text = kinogaki_document_save_text(s, &n); /* → .prisma bytes you own */
fwrite(text, 1, n, stdout);
kinogaki_free_buffer(text);
kinogaki_document_free(s);
Already have a coding agent? Skip the hand-written FFI: pip install kinogaki wraps exactly this surface in a Pythonic API.
The shape of the surface
The naming is uniform (kinogaki_<noun>_<verb>) and the lifecycle is explicit:
- handles:
kinogaki_document_t*, plus handles for the evaluator and the node registry where needed; - build:
kinogaki_document_new,kinogaki_document_add_element, the typed setters (kinogaki_element_set_float,…_set_int,…_set_float3, vector/array variants),kinogaki_document_connect; - read: typed getters (
kinogaki_element_get_float, …) that resolve a property at a time, andkinogaki_evaluateto resolve through connections; - I/O:
kinogaki_document_save_text/…_save_binary/kinogaki_document_loadfor the native ASCII and binary encodings; - free:
kinogaki_document_free, andkinogaki_free_bufferfor any buffer the library handed back.
Ownership rules
The contract is the usual C one, kept deliberately small: the library owns nothing you pass in (strings are copied at the boundary), and you own every buffer the library returns. Release a buffer with kinogaki_free_buffer, and release handles with their _free. Errors are reported through return codes and an out-parameter message rather than exceptions, because exceptions do not cross a C boundary.
Why it's there
The C ABI makes Core reachable from any language. The same document a C++ tool builds, the Server edits, and a human writes by hand can also be created and read from a Python notebook or a Rust service through this surface, with the same paths, the same typed values, the same files. Bind it once for your language and the entire document model is available, with C++ kept out of your call sites.