Basic Publisher/Subscriber Example
This example demonstrates a simple publisher and subscriber using AstuteDDS.
Define Data Type (IDL)
// hello.idl
module HelloWorld {
struct Message {
@key long id;
string text;
};
};
Compile IDL
./build/tools/idl_compiler/astutedds-idl hello.idl
Publisher
#include "Message.hpp"
#include "Message_TypeSupport.hpp"
#include <astutedds/dcps/domain_participant.hpp>
#include <astutedds/dcps/publisher.hpp>
int main() {
using namespace astutedds::dcps;
// Create domain participant using the factory
auto& factory = DomainParticipantFactory::instance();
DomainParticipantQos pqos; // Use default QoS
auto* participant = factory.create_participant(0, pqos);
if (!participant) {
std::cerr << "Failed to create participant" << std::endl;
return 1;
}
// Enable the participant to start discovery
if (!participant->enable()) {
std::cerr << "Failed to enable participant" << std::endl;
return 1;
}
// Create topic with topic name and type name
TopicQos tqos; // Use default topic QoS
auto* topic = participant->create_topic("HelloTopic", "HelloWorld::Message", tqos);
if (!topic) {
std::cerr << "Failed to create topic" << std::endl;
return 1;
}
// Create publisher
PublisherQos pubqos; // Use default publisher QoS
auto* publisher = participant->create_publisher(pubqos);
if (!publisher) {
std::cerr << "Failed to create publisher" << std::endl;
return 1;
}
// Create writer
DataWriterQos wqos; // Use default writer QoS
auto* writer = publisher->create_datawriter(topic, wqos);
if (!writer) {
std::cerr << "Failed to create writer" << std::endl;
return 1;
}
// Write data (serialized as XCDR)
HelloWorld::Message msg;
msg.id = 1;
msg.text = "Hello, DDS!";
// Serialize the message to XCDR bytes
std::vector<uint8_t> serialized;
HelloWorld::MessageTypeSupport::serialize(msg, serialized);
if (writer->write(serialized)) {
std::cout << "Published: " << msg.text << std::endl;
} else {
std::cerr << "Failed to publish message" << std::endl;
}
// Cleanup
publisher->delete_datawriter(writer);
participant->delete_publisher(publisher);
participant->delete_topic(topic);
factory.delete_participant(participant);
return 0;
}
Subscriber
#include "Message.hpp"
#include "Message_TypeSupport.hpp"
#include <astutedds/dcps/domain_participant.hpp>
#include <astutedds/dcps/subscriber.hpp>
#include <iostream>
#include <thread>
#include <chrono>
int main() {
using namespace astutedds::dcps;
// Create domain participant using the factory
auto& factory = DomainParticipantFactory::instance();
DomainParticipantQos pqos; // Use default QoS
auto* participant = factory.create_participant(0, pqos);
if (!participant) {
std::cerr << "Failed to create participant" << std::endl;
return 1;
}
// Enable the participant to start discovery
if (!participant->enable()) {
std::cerr << "Failed to enable participant" << std::endl;
return 1;
}
// Create topic with topic name and type name
TopicQos tqos; // Use default topic QoS
auto* topic = participant->create_topic("HelloTopic", "HelloWorld::Message", tqos);
if (!topic) {
std::cerr << "Failed to create topic" << std::endl;
return 1;
}
// Create subscriber
SubscriberQos subqos; // Use default subscriber QoS
auto* subscriber = participant->create_subscriber(subqos);
if (!subscriber) {
std::cerr << "Failed to create subscriber" << std::endl;
return 1;
}
// Create reader
DataReaderQos rqos; // Use default reader QoS
auto* reader = subscriber->create_datareader(topic, rqos);
if (!reader) {
std::cerr << "Failed to create reader" << std::endl;
return 1;
}
// Read data
SampleInfo info;
std::vector<uint8_t> serialized;
while (true) {
if (reader->read_next_sample(serialized, info) == ReturnCode_t::RETCODE_OK && info.valid_data) {
// Deserialize the message from XCDR bytes
HelloWorld::Message msg;
HelloWorld::MessageTypeSupport::deserialize(msg, serialized);
std::cout << "Received: " << msg.text << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Cleanup (unreachable, but good practice)
subscriber->delete_datareader(reader);
participant->delete_subscriber(subscriber);
participant->delete_topic(topic);
factory.delete_participant(participant);
return 0;
}
Build and Run
Link Against AstuteDDS
# Compile publisher
g++ -std=c++20 publisher.cpp -o publisher \
-I. \
-I/usr/local/include/astutedds \
-L/usr/local/lib \
-lastutedds
# Compile subscriber
g++ -std=c++20 subscriber.cpp -o subscriber \
-I. \
-I/usr/local/include/astutedds \
-L/usr/local/lib \
-lastutedds
# Ensure library path is set
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
# Run in separate terminals
./publisher
./subscriber
Using CMake
Alternatively, use CMake for a more portable build:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 20)
find_package(AstuteDDS REQUIRED)
add_executable(publisher publisher.cpp)
target_link_libraries(publisher PRIVATE AstuteDDS::astutedds)
add_executable(subscriber subscriber.cpp)
target_link_libraries(subscriber PRIVATE AstuteDDS::astutedds)
Build:
mkdir build && cd build
cmake ..
cmake --build .
./publisher
./subscriber