Rust Quick Start

A minimal publisher and subscriber that exchange UTF-8 strings on HelloWorldTopic.

Project layout

my_dds_app/
├── Cargo.toml
└── src/
    ├── hello_publisher.rs
    └── hello_subscriber.rs
# Cargo.toml
[package]
name    = "my_dds_app"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "hello_publisher"
path = "src/hello_publisher.rs"

[[bin]]
name = "hello_subscriber"
path = "src/hello_subscriber.rs"

[dependencies]
astutedds = { path = "/path/to/astutedds-cxx/bindings/rust/astutedds" }

Subscriber

// src/hello_subscriber.rs
use astutedds::{DataReaderQos, DomainParticipant, Error, Reliability};
use std::time::{Duration, Instant};

fn main() -> astutedds::Result<()> {
    let dp    = DomainParticipant::new(0)?;
    let topic = dp.create_topic("HelloWorldTopic", "HelloWorld")?;
    let sub   = dp.create_subscriber()?;

    let qos = DataReaderQos {
        reliability: Reliability::ASTUTEDDS_RELIABLE,
        ..Default::default()
    };
    let reader = sub.create_datareader(&topic, qos)?;

    println!("[SUB] Waiting for messages (30 s timeout)…");
    let deadline = Instant::now() + Duration::from_secs(30);

    while Instant::now() < deadline {
        match reader.take_next() {
            Ok(bytes) => {
                let msg = std::str::from_utf8(&bytes).unwrap_or("<binary>");
                println!("[SUB] Received: {msg}");
            }
            Err(Error::NoData) => std::thread::sleep(Duration::from_millis(100)),
            Err(e)             => return Err(e),
        }
    }
    Ok(())
}

Publisher

// src/hello_publisher.rs
use astutedds::{DataWriterQos, DomainParticipant, Reliability};
use std::time::Duration;

fn main() -> astutedds::Result<()> {
    let dp    = DomainParticipant::new(0)?;
    let topic = dp.create_topic("HelloWorldTopic", "HelloWorld")?;
    let pub_  = dp.create_publisher()?;

    let qos = DataWriterQos {
        reliability: Reliability::ASTUTEDDS_RELIABLE,
        ..Default::default()
    };
    let writer = pub_.create_datawriter(&topic, qos)?;

    for i in 1..=10 {
        let msg = format!("Hello, DDS! #{i}");
        println!("[PUB] Writing: {msg}");
        writer.write(msg.as_bytes())?;
        std::thread::sleep(Duration::from_millis(500));
    }
    Ok(())
}

Run it

In one terminal:

ASTUTEDDS_LIB_DIR=/path/to/astutedds-cxx/build/lib \
    cargo run --release --bin hello_subscriber

In another:

ASTUTEDDS_LIB_DIR=/path/to/astutedds-cxx/build/lib \
    cargo run --release --bin hello_publisher

What just happened?

  1. DomainParticipant::new(0) joined DDS domain 0. The returned value is an RAII guard — when dp goes out of scope the participant is deleted and all owned entities are cleaned up.
  2. create_topic registered a topic name + type-name binding. Type compatibility on the wire is matched on the type-name string.
  3. The publisher created a DataWriter; the subscriber created a matching DataReader. Lifetimes ensure they cannot outlive their parent topic / participant.
  4. The publisher wrote raw byte payloads. The subscriber polled with take_next(), which returns Err(Error::NoData) when the cache is empty — a clean signal to back off and retry.