Separation of concerns at the call boundary
Canopy keeps interface shape, transport, serialization, error flow, and deployment topology
from collapsing into the same hand-written client/server code. The generated interface is
the stable part; streams, transports, and serializers can change underneath it.
Interface-first development
Define the service shape once in IDL. Canopy generates type-safe C++ proxy and stub code via
a CMake command. The same interface works across local, process, network, and enclave
transports — change the transport at construction time, not in application code.
Composable streams
TCP, TLS, SPSC shared-memory, WebSocket, and io_uring layers compose below the RPC layer
without rewriting application contracts. Wrap a TCP stream in SPSC buffering, then in TLS —
each layer only knows the stream interface below it.
Bi-modal execution
The same C++ implementation compiles in both blocking mode (straightforward, easy to debug)
and C++20 co_await coroutine mode (high-throughput, scalable).
CO_AWAIT and CO_RETURN macros switch between modes at compile time
— your code does not change.
Callbacks, streaming, and fire-and-forget
Bidirectional callbacks let the server push to the client. Methods marked [post]
are one-way — the caller continues immediately with no reply wait. Useful for LLM token
delivery, price data feeds, telemetry, and high-throughput video.
Remote object lifetimes
rpc::shared_ptr<T> maintains a distributed reference count across machine
boundaries: if Machine A shares an object with B and B passes it to C, the object stays
alive until both B and C release it. rpc::optimistic_ptr<T> provides a
lighter callable reference for long-lived services, circular reference breaks, and objects
whose availability is managed outside the immediate call.
Multiple interfaces and runtime polymorphism
A single remote object can implement multiple interfaces. Callers hold a proxy to one
interface and can cast to any other the object supports — the cast is performed against the
live object in its zone, preserving full C++ polymorphism across supported transports.