Header-only C++17 wrapper over libreflow_rt_capi. Same RAII shape
the other SDKs use: every handle is owned by a unique_ptr with a
custom deleter, errors throw reflow::Error, and JSON-shaped returns
come back as std::string so you can plug in whatever JSON library
you prefer.
#include <reflow/reflow.hpp>
reflow::Graph g("demo");
g.add_node("a", "tpl_x");
g.add_node("b", "tpl_y");
g.add_connection("a", "out", "b", "in");
g.add_initial("a", "in", R"({"type":"Integer","data":42})");
std::cout << g.to_json() << "\n";- C++17 compiler (clang ≥ 9, gcc ≥ 9, MSVC 2019+)
libreflow_rt_capi.{so,dylib,dll}for your platform
The runtime library is not bundled with this header. Two paths:
The Go SDK's publish-go workflow ships per-triple tarballs to
Releases on
every sdk/go/v* tag. Each tarball contains exactly the files this
SDK needs — lib/libreflow_rt_capi.{dylib,so,dll} and
include/reflow_rt.h. Download, untar, and point CMake at it.
VER=0.2.3
TRIPLE=aarch64-apple-darwin # or x86_64-apple-darwin, x86_64-unknown-linux-gnu, …
curl -LO https://github.com/offbit-ai/reflow/releases/download/sdk/go/v$VER/reflow-rt-capi-$TRIPLE-v$VER.tar.gz
tar -xzf reflow-rt-capi-$TRIPLE-v$VER.tar.gz -C /usr/localcargo build -p reflow_rt_capi --release
# → target/release/libreflow_rt_capi.{dylib,so,dll}add_subdirectory(third_party/reflow/sdk/cpp)
target_link_libraries(myapp PRIVATE reflow::cpp)If find_library(reflow_rt_capi) doesn't pick up the runtime, point
it explicitly:
set(REFLOW_RT_CAPI_LIB "/usr/local/lib/libreflow_rt_capi.dylib")
add_subdirectory(third_party/reflow/sdk/cpp)Or do the install + find_package flow:
cmake -S sdk/cpp -B build && cmake --install build --prefix /usr/localfind_package(reflow REQUIRED)
target_link_libraries(myapp PRIVATE reflow::cpp)The header mirrors crates/reflow_rt_capi/include/reflow_rt.h 1:1
with C++ ergonomics:
| C ABI | C++ |
|---|---|
rfl_graph_* |
reflow::Graph |
rfl_network_* |
reflow::Network |
rfl_actor_new / rfl_template_actor_new |
reflow::Actor |
rfl_message_* |
reflow::Message |
rfl_events_* |
reflow::EventStream |
rfl_subgraph_builder_* |
reflow::SubgraphBuilder |
rfl_template_list_json |
reflow::template_list_json() |
rfl_compose_graphs |
reflow::compose_graphs(json) |
rfl_pack_load / rfl_pack_* |
reflow::pack::load(...) etc. |
reflow::pack::load("./reflow.pack.gpu-0.2.0.rflpack") accepts
either the full multi-triple bundle or a per-triple slim
(<name>-<version>-<triple>.rflpack) — the loader picks the
binary that matches the runtime triple at load time, so for a
known target you can ship the ~3 MiB slim instead of the ~22 MiB
full bundle. See sdk/packs/README.md
for download links.
Every C call that returns rfl_status is checked; non-OK throws
reflow::Error, whose what() includes both the operation and the
runtime's last error message (the same string rfl_last_error_message
returns). The exception also carries the original rfl_status via
error.status() if you need to discriminate programmatically.
try {
g.remove_node("nope");
} catch (const reflow::Error& e) {
std::cerr << e.what() << " (status=" << e.status() << ")\n";
}Methods like Graph::nodes_json() / connections_json() /
get_node_json(id) return std::string (or std::optional<std::string>
for query misses). The library doesn't bundle a JSON parser — pick
nlohmann/json,
simdjson, or whatever you
already use.
#include <nlohmann/json.hpp>
auto nodes = nlohmann::json::parse(g.nodes_json());
for (auto& n : nodes) std::cout << n["id"].get<std::string>() << "\n";auto doubler = reflow::Actor::from_callback(
"doubler", {"in"}, {"out"},
[](rfl_actor_ctx* ctx) -> rfl_status {
char* in = rfl_ctx_input_json(ctx, "in");
if (!in) return rfl_status_Ok; // no input this tick
// … parse, compute, emit …
rfl_string_free(in);
return rfl_status_Ok;
});
reflow::Network net;
net.register_actor("tpl_doubler", std::move(doubler));cmake -S sdk/cpp -B build -DREFLOW_CPP_BUILD_EXAMPLES=ON \
-DREFLOW_RT_CAPI_LIB=$PWD/target/release/libreflow_rt_capi.dylib
cmake --build build
build/reflow_cpp_quickstartThe C++ wrapper tracks the C ABI version of the runtime it was built
against. There's no separate package: pull the header alongside any
matching libreflow_rt_capi release. The header's
reflow::pack::abi_version() returns the same number as the runtime,
so you can sanity-check at startup if you load packs.
MIT OR Apache-2.0, matching the rest of the repository.