RPC for stateful resources.
C-Two is a resource-oriented RPC runtime for distributed scientific computation. It exposes stateful objects—simulations, spatial indexes and data processors—across processes and machines. Clients use the same method interface for local and remote resources.
A CRM contract declares the callable methods and their namespace/version. A resource is a plain class that implements those methods and holds state. A client uses cc.connect(...) to obtain a typed proxy. A process can host several resources and connect to other resources at the same time.
C-Two 0.10.1 supports Python 3.10+. Ordinary calls have no Python runtime dependencies; FastDB payloads use c-two[fastdb] (fastdb4py==0.2.4). IPC handshake 14 reports a version mismatch as a typed error, Unix endpoint namespaces use format 3 with versioned default directories, and Python adds independent cc.Runtime() instances and cc.endpoint.server_credential(). A failed memory release stays with its owner for retry, or is abandoned conservatively and counted when it can no longer be returned. See the 0.10.0 release notes; 0.10.1 keeps cc.serve() running when stdout cannot encode its messages (notes).
- Local and remote calls: same-process calls pass Python objects directly; same-host IPC uses Unix domain sockets or Windows Named Pipes; cross-machine calls use HTTP relay. Explicit IPC connections work independently of relay discovery.
- State and concurrency: resources keep their state between calls.
@cc.readand@cc.writedeclare access semantics, with writes as the default. Native route scheduling enforces concurrency and pending-work limits across local and remote invocation. - Portable contracts and payloads:
@cc.transfer(...)binds FastDBPayloadspecifications. Contract tooling validates descriptors and generates Python, Rust and TypeScript bindings; ordinary Python values also support Python-to-Python calls. - Contract-scoped routing: clients match the route name, CRM identity and contract hashes. Relay discovery selects a verified local IPC path or an HTTP target;
c3runs the relay and supports relay meshes. - Native memory transport: IPC uses lazy buddy pools, dedicated shared memory, checked chunk transfer and file spill. Budgets and idle reclamation control memory and file usage for large payloads. See memory policy.
- Explicit payload lifetimes:
cc.hold()retains response leases, while registration can select borrowed input lifetimes. Release invalidates payload owners and checked views before releasing transport storage. See Python payload usage. - Connection observations:
cc.observe.connection_events()aggregates outgoing and accepted physical IPC connections; one cancellable consumer replaces per-connection blocking waits. Reasons describe transport facts, not proof of process death. - Resource lifecycle management: Native shutdown drains work, and scoped endpoint maintenance cleans up confirmed exits. See lifecycle integration.
- Shared Rust core: Python and Rust use the same routing, transport, memory, error and lifecycle mechanisms. The native c3 CLI handles relay, contract tools and endpoint maintenance on Linux, macOS and Windows x64 and ARM64.
uv pip install c-two
# For FastDB payloads:
uv pip install 'c-two[fastdb]'The same command works in Windows PowerShell. For c3 on Linux or macOS:
curl -fsSL https://github.com/world-in-progress/c-two/releases/download/c3-v0.6.0/c3-installer.sh | sh -s -- --version 0.6.0On Windows x64 or ARM64, use the x64 executable, ARM64 executable or PowerShell installer. Installation and checksum verification are in the Windows guide.
C3 0.6.0 pairs with C-Two 0.10.x. IPC handshake 14 cannot interoperate with 0.9.x peers (IPC 13), and Unix endpoint namespace format 3 uses new default directories, so upgrade the Python and Rust SDKs, c3 and Node consumers on one host together; stop old services before upgrading and restarting. C/FFI ABI 6 and SHM 3 keep their formats. See the 0.10.0 migration notes, the handshake spec and the endpoint lifecycle guide.
Source builds need Rust 1.95 or newer; for builds and tests, see the development guide.
Save as counter.py:
import c_two as cc
@cc.crm(namespace='demo.counter', version='0.1.0')
class Counter:
def increment(self, amount: int) -> int: ...
class CounterResource:
def __init__(self):
self.value = 0
def increment(self, amount: int) -> int:
self.value += amount
return self.value
cc.register(Counter, CounterResource(), name='counter')
try:
with cc.connect(Counter, name='counter') as counter:
print(counter.increment(3)) # 3
finally:
cc.shutdown()Run with python counter.py. This example uses the same-process path; keep C2_RELAY_ANCHOR_ADDRESS unset for local registration.
For another process on the same host, pass the resource process's cc.server_address() as the client's address; the IPC example shows this connection. The resource process can also capture credential = cc.endpoint.server_credential() after registration and pass it to its controller for later exact cleanup, as described in the lifecycle guide.
runtime = cc.Runtime() creates an application-owned Python Runtime with its own configuration, routes and native session. Configure it through runtime.set_*(), then use runtime.start() for an empty Host readiness check or runtime.register() for resources. The module functions continue to use the default runtime; cc.serve() owns its process signal handling and has no instance equivalent. Call runtime.shutdown() and inspect its structured outcome when the application is done; if it returns pending, call shutdown again to observe completion and replace the session. See the independent runtime example and Python API guide.
For relay routing, start c3 relay --bind 0.0.0.0:8300, set cc.set_relay_anchor('http://relay-host:8300') on both sides, then connect by name. The relay is a separate process. Explicit IPC addresses bypass relay discovery.
| Topic | Guide |
|---|---|
| Local calls | local.py |
| Direct IPC | resource, client |
| Independent Python Runtime | owned endpoint preflight |
| Relay | resource, client, mesh |
Configuration: code, environment and .env |
Configuration guide |
| Python contracts, portable payloads and API index | Python SDK guide |
| Rust SDK and API migration | Rust SDK guide |
| Relay and contract tools | c3 CLI guide |
| Connection and endpoint APIs | Lifecycle guide |
| IPC handshake protocol | Handshake spec |
| Windows | Build and usage |
| Environment variables | .env.example |
| Development | Build and tests, CI and releases, contributing |
MIT.
