Hello World in C++
This tutorial covers building the temperature sensor application using modern C++17 with HDDS.
Time: ~10 minutes Prerequisites: HDDS C++ library installed
Step 1: Create the IDL File
Create Temperature.idl:
module sensors {
@topic
struct Temperature {
@key string sensor_id;
float value;
unsigned long long timestamp;
};
};
Step 2: Generate C++ Code
hdds-gen -l cpp Temperature.idl
This generates:
Temperature.hpp- Type definitions with modern C++ featuresTemperature.cpp- Serialization implementation
Step 3: Create the Publisher
Create publisher.cpp:
#include <iostream>
#include <chrono>
#include <thread>
#include <hdds/hdds.hpp>
#include "Temperature.hpp"
using namespace std::chrono_literals;
int main() {
std::cout << "Starting temperature publisher..." << std::endl;
try {
// 1. Create DomainParticipant
hdds::DomainParticipant participant(0);
std::cout << "Joined domain 0" << std::endl;
// 2. Create Topic
auto topic = participant.create_topic<sensors::Temperature>("temperature/room1");
std::cout << "Created topic: temperature/room1" << std::endl;
// 3. Create Publisher and DataWriter
auto publisher = participant.create_publisher();
auto writer = publisher.create_writer(topic);
std::cout << "DataWriter created, waiting for subscribers..." << std::endl;
// 4. Wait for subscribers
writer.wait_for_subscribers(1, 30s);
std::cout << "Subscriber connected!" << std::endl;
// 5. Publish temperature readings
for (int i = 0; i < 10; ++i) {
sensors::Temperature temp;
temp.sensor_id = "sensor-001";
temp.value = 22.0f + (i * 0.5f);
temp.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
writer.write(temp);
std::cout << "Published: sensor=" << temp.sensor_id
<< ", temp=" << temp.value << "°C" << std::endl;
std::this_thread::sleep_for(1s);
}
std::cout << "Publisher finished" << std::endl;
} catch (const hdds::Exception& e) {
std::cerr << "HDDS Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
Step 4: Create the Subscriber
Create subscriber.cpp:
#include <iostream>
#include <chrono>
#include <hdds/hdds.hpp>
#include "Temperature.hpp"
using namespace std::chrono_literals;
int main() {
std::cout << "Starting temperature subscriber..." << std::endl;
try {
// 1. Create DomainParticipant
hdds::DomainParticipant participant(0);
std::cout << "Joined domain 0" << std::endl;
// 2. Create Topic
auto topic = participant.create_topic<sensors::Temperature>("temperature/room1");
std::cout << "Created topic: temperature/room1" << std::endl;
// 3. Create Subscriber and DataReader
auto subscriber = participant.create_subscriber();
auto reader = subscriber.create_reader(topic);
std::cout << "DataReader created, waiting for data..." << std::endl;
// 4. Read samples in a loop
while (true) {
if (reader.wait_for_data(5s)) {
// Take all available samples
for (auto& sample : reader.take()) {
std::cout << "Received: sensor=" << sample.data().sensor_id
<< ", temp=" << sample.data().value << "°C"
<< ", time=" << sample.data().timestamp << std::endl;
}
} else {
std::cout << "No data received in 5 seconds, waiting..." << std::endl;
}
}
} catch (const hdds::Exception& e) {
std::cerr << "HDDS Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
Step 5: Create CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(hdds-hello-world CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(hdds REQUIRED)
# Generate type support
hdds_generate_cpp(GENERATED_SRCS Temperature.idl)
# Publisher
add_executable(publisher publisher.cpp ${GENERATED_SRCS})
target_link_libraries(publisher PRIVATE hdds::hdds-cpp)
# Subscriber
add_executable(subscriber subscriber.cpp ${GENERATED_SRCS})
target_link_libraries(subscriber PRIVATE hdds::hdds-cpp)
Step 6: Build and Run
mkdir build && cd build
cmake ..
cmake --build .
# Terminal 1
./subscriber
# Terminal 2
./publisher
Modern C++ Features
Range-based Iteration
for (auto& sample : reader.take()) {
if (sample.info().valid_data) {
process(sample.data());
}
}
Lambda Callbacks
reader.on_data_available([](auto& reader) {
for (auto& sample : reader.take()) {
std::cout << "Received: " << sample.data().value << std::endl;
}
});
Async/Await (C++20)
#include <hdds/hdds_async.hpp>
hdds::task<void> run_subscriber() {
hdds::DomainParticipant participant(0);
auto topic = participant.create_topic<sensors::Temperature>("temperature/room1");
auto reader = participant.create_subscriber().create_reader(topic);
while (true) {
auto samples = co_await reader.take_async();
for (auto& sample : samples) {
std::cout << "Received: " << sample.data().value << std::endl;
}
}
}
RAII Resource Management
All HDDS C++ objects use RAII. No manual cleanup needed:
{
hdds::DomainParticipant participant(0);
auto writer = participant.create_publisher()
.create_writer(topic);
writer.write(data);
} // Everything cleaned up automatically
QoS Configuration
// Reliable with history
auto writer_qos = hdds::DataWriterQos()
.reliability(hdds::Reliability::Reliable(1s))
.history(hdds::History::KeepLast(10))
.durability(hdds::Durability::TransientLocal);
auto writer = publisher.create_writer(topic, writer_qos);
What's Next?
- Hello World Python - Python version
- C++ API Reference - Complete C++ documentation