This guide helps developers familiar with cyclonedds-python transition to cyclonedds-rust.
| Aspect | Python | Rust |
|---|---|---|
| Type safety | Runtime | Compile-time |
| Memory management | GC | Ownership + RAII |
| Serialization | Automatic (Cython) | Derive macro or manual DdsType impl |
| Async model | asyncio + custom waitset |
tokio + native Stream impl |
| Error handling | Exceptions | Result<T, DdsError> |
| Python | Rust |
|---|---|
DomainParticipant(domain_id) |
DomainParticipant::new(domain_id)? |
Publisher(participant) |
Publisher::new(&participant)? |
Subscriber(participant) |
Subscriber::new(&participant)? |
Topic(participant, "Name", T) |
Topic::<T>::new(&participant, "Name")? |
DataWriter(publisher, topic) |
DataWriter::new(&publisher, &topic)? |
DataReader(subscriber, topic) |
DataReader::<T>::new(&subscriber, &topic)? |
Python uses a fluent builder:
from cyclonedds.qos import Qos, Policy
qos = Qos(Policy.Reliability.BestEffort)Rust uses QosBuilder:
use cyclonedds::QosBuilder;
let qos = QosBuilder::new().reliable().build();Python:
samples = reader.take()
for s in samples:
print(s.data)Rust:
let samples: Vec<T> = reader.take()?;
for s in samples {
println!("{:?}", s);
}Note: Rust's take() returns Vec<T> directly, not wrapped in Sample objects. If you need metadata (timestamp, instance state), use reader.read_with_metadata() or similar advanced APIs.
Rust provides native Stream support (Python does not have an equivalent):
use futures_util::StreamExt;
let mut stream = Box::pin(reader.read_aiter());
while let Some(batch) = stream.next().await {
match batch {
Ok(samples) => println!("got {} samples", samples.len()),
Err(e) => eprintln!("read error: {}", e),
}
}Both Python and Rust use closure-based filtering (CycloneDDS C does not expose SQL content filters):
Python:
from cyclonedds.topic import ContentFilteredTopic
cft = ContentFilteredTopic(topic, lambda s: s.id > 10)Rust:
let cft = ContentFilteredTopic::new(&topic, |s: &T| s.id > 10)?;| Python | Rust |
|---|---|
cyclonedds ls |
cargo run --bin cyclonedds-cli -- ls |
cyclonedds ps |
cargo run --bin cyclonedds-cli -- ps |
cyclonedds subscribe |
cargo run --bin cyclonedds-cli -- subscribe |
cyclonedds typeof |
cargo run --bin cyclonedds-cli -- typeof |
cyclonedds publish |
cargo run --bin cyclonedds-cli -- publish |
- Entity handles: Rust uses
entity()to get the raw handle; Python entities are handles directly. - Lifetime: Rust
Topic,DataReader,DataWriterare bound to their parent participant's lifetime. Dropping the participant invalidates children. - Type registration: In Rust,
Topic::<T>requiresT: DdsType. Use#[derive(DdsTypeDerive)]or implement the trait manually. - No
Sample<T>wrapper: Unlike Python, Rustread()/take()returnVec<T>directly.
~96% of cyclonedds-python APIs are available in Rust. Notable gaps:
- SQL Content Filters: Neither Python nor Rust supports SQL syntax; both use closures.
- QueryCondition SQL: Same as above — C API limitation.
- QoS merge/diff: Not exposed in Python or Rust.
See the API Guide for a complete tour of Rust-specific features like zero-copy loans and matched endpoint data.