Cross-Language Interop

HORUS lets you mix C++, Rust, and Python in the same system. All three languages share the same shared-memory ring buffers — a C++ publisher and a Python subscriber read from the exact same memory. Zero serialization, zero copying for Pod types.

How It Works

C++ Process          Rust Process          Python Process
┌──────────┐         ┌──────────┐         ┌──────────┐
│ Publisher │──SHM───→│Subscriber│         │          │
│  CmdVel  │    │    │  CmdVel  │──SHM───→│Subscriber│
└──────────┘    │    └──────────┘         │  CmdVel  │
                │                          └──────────┘
                └─ Same /dev/shm/horus_default/topics/cmd_vel file

All three open the same SHM file. The ring buffer header and data layout are identical regardless of language.

Requirements

For cross-language communication:

  1. Use the same topic name (e.g., "cmd_vel")
  2. Use the same message type (e.g., CmdVel — a Pod struct with identical memory layout)
  3. Processes must run on the same machine (SHM is local)

Example: C++ Sensor + Python AI + Rust Controller

C++ Sensor Driver (10 Hz)

#include <horus/horus.hpp>

int main() {
    horus::Scheduler sched;
    horus::Publisher<horus::msg::CmdVel> pub("sensor.data");

    sched.add("lidar_driver")
        .order(0)
        .tick([&] {
            auto msg = pub.loan();
            msg->linear = 1.2f;   // range reading
            msg->angular = 0.0f;
            pub.publish(std::move(msg));
        })
        .build();

    sched.spin();
}

Python AI Processor

import horus

def detector_tick(node):
    scan = node.recv("sensor.data")
    if scan is not None:
        # Run ML inference on sensor data
        obstacle = scan.linear < 0.5
        node.send("ai.decision", horus.CmdVel(
            linear=0.0 if obstacle else 0.3,
            angular=0.5 if obstacle else 0.0
        ))

horus.run(
    horus.Node(
        name="ai_detector",
        subs=["sensor.data"],
        pubs=["ai.decision"],
        tick=detector_tick,
        rate=10
    )
)

Rust Motor Controller (100 Hz)

use horus::prelude::*;

node! {
    MotorCtrl {
        sub { cmd: CmdVel -> "ai.decision" }
        data { last_linear: f64 = 0.0 }
        tick {
            if let Some(c) = self.cmd.recv() {
                self.last_linear = c.linear as f64;
                // Apply to motors...
            }
        }
    }
}

fn main() -> Result<()> {
    let mut sched = Scheduler::new().tick_rate(100.hz());
    sched.add(MotorCtrl::new()).build()?;
    sched.run()
}

Run All Three

# Terminal 1: C++ sensor
horus run --project cpp_sensor/

# Terminal 2: Python AI
horus run --project py_detector/

# Terminal 3: Rust controller
horus run --project rust_ctrl/

All three share topics over SHM. Use horus topic list to see all active topics from any terminal.

Message Type Compatibility

For cross-language topics, use typed Pod messages (not generic dicts):

C++ TypeRust TypePython Type
horus::msg::CmdVelhorus_library::CmdVelhorus.CmdVel
horus::msg::Imuhorus_library::Imuhorus.Imu
horus::msg::LaserScanhorus_library::LaserScanhorus.LaserScan
horus::msg::Odometryhorus_library::Odometryhorus.Odometry
horus::msg::JointStatehorus_library::JointStatehorus.JointState
horus::msg::Pose2Dhorus_library::Pose2Dhorus.Pose2D
horus::msg::Twisthorus_library::Twisthorus.Twist

All share the same #[repr(C)] memory layout. A CmdVel written by C++ is byte-identical to one written by Rust or Python.

CLI Works Across Languages

No matter which language published the message:

horus topic list         # shows topics from C++, Rust, and Python nodes
horus topic echo cmd_vel # receives messages regardless of publisher language
horus node list          # shows all nodes with PID and language

Performance

PathLatency
Rust to Rust (same process)11 ns
C++ to C++ (same process)15 ns (11 + 4 FFI)
C++ to Rust (cross-process)170 ns
Rust to Python (cross-process)~300 ns
C++ to Python (cross-process)~300 ns

Cross-process latency is dominated by SHM synchronization, not language boundaries.

When to Use Each Language

ComponentRecommended LanguageWhy
Sensor driversC++ or RustDirect hardware access, low latency
AI/ML inferencePythonPyTorch, TensorFlow, NumPy ecosystem
Control loopsRust or C++Determinism, real-time guarantees
Monitoring/loggingPythonRapid development, visualization
Safety systemsRustCompile-time guarantees, no undefined behavior
Legacy integrationC++Existing codebase compatibility