Aller au contenu principal

Hello World en C++

Ce tutoriel couvre la construction de l'application de capteur de temperature en utilisant le C++17 moderne avec HDDS.

Duree : ~10 minutes Prerequis : Bibliotheque C++ HDDS installee

Etape 1 : Creer le fichier IDL

Creez Temperature.idl :

module sensors {
@topic
struct Temperature {
@key string sensor_id;
float value;
unsigned long long timestamp;
};
};

Etape 2 : Generer le code C++

hdds-gen -l cpp Temperature.idl

Cela genere :

  • Temperature.hpp - Definitions de types avec des fonctionnalites C++ modernes
  • Temperature.cpp - Implementation de la serialisation

Etape 3 : Creer le Publisher

Creez 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;
}

Etape 4 : Creer le Subscriber

Creez 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;
}

Etape 5 : Creer le 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)

Etape 6 : Compiler et executer

mkdir build && cd build
cmake ..
cmake --build .

# Terminal 1
./subscriber

# Terminal 2
./publisher

Fonctionnalites C++ modernes

Iteration range-based

for (auto& sample : reader.take()) {
if (sample.info().valid_data) {
process(sample.data());
}
}

Callbacks Lambda

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;
}
}
}

Gestion des ressources RAII

Tous les objets C++ HDDS utilisent le RAII. Aucun nettoyage manuel necessaire :

{
hdds::DomainParticipant participant(0);
auto writer = participant.create_publisher()
.create_writer(topic);
writer.write(data);
} // Everything cleaned up automatically

Configuration QoS

// 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);

Prochaines etapes