3. 数组与序列消息
任务目标
在FastDDS中,IDL支持两种批量数据类型:固定数组(定长,编译期确定)与可变序列(动态长度,运行时确定)。本案例将定义同时包含这两种字段的消息类型,并完成一个发布-订阅闭环,验证数据正确传输。
IDL定义
创建 ArraySeq.idl:
struct ArraySeqMessage
{
long fixed_array[4]; // 固定数组,长度4
sequence<long> dynamic_seq; // 可变序列,长度不限
};
完整实现代码
以下为单个可编译运行的C++源文件,包含发布端与订阅端逻辑(使用FastDDS 2.x API):
#include <iostream>
#include <thread>
#include <chrono>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/SampleInfo.hpp>
#include "ArraySeqPubSubTypes.h" // 由fastddsgen生成
using namespace eprosima::fastdds::dds;
class SubListener : public DataReaderListener
{
public:
bool received = false;
void on_data_available(DataReader* reader) override
{
ArraySeqMessage msg;
SampleInfo info;
while (reader->take_next_sample(&msg, &info) == ReturnCode_t::RETCODE_OK)
{
if (info.valid_data)
{
std::cout << "收到消息: fixed_array = [";
for (int i = 0; i < 4; ++i)
std::cout << msg.fixed_array()[i] << (i < 3 ? ", " : "");
std::cout << "], dynamic_seq = [";
for (auto it = msg.dynamic_seq().begin(); it != msg.dynamic_seq().end(); ++it)
std::cout << *it << (std::next(it) != msg.dynamic_seq().end() ? ", " : "");
std::cout << "]" << std::endl;
received = true;
}
}
}
};
int main()
{
// 创建参与者
DomainParticipant* participant = DomainParticipantFactory::get_instance()->create_participant(0);
if (!participant) return -1;
// 注册类型
TypeSupport type(new ArraySeqMessagePubSubType());
type.register_type(participant);
// 创建主题
Topic* topic = participant->create_topic("ArraySeqTopic", type.get_type_name(), TOPIC_QOS_DEFAULT);
// 创建发布端
Publisher* pub = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
DataWriter* writer = pub->create_datawriter(topic, DATAWRITER_QOS_DEFAULT);
// 创建订阅端
Subscriber* sub = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
SubListener listener;
DataReader* reader = sub->create_datareader(topic, DATAREADER_QOS_DEFAULT, &listener);
// 等待匹配
std::this_thread::sleep_for(std::chrono::seconds(1));
// 构造并发送消息
ArraySeqMessage msg;
for (int i = 0; i < 4; ++i)
msg.fixed_array()[i] = i * 10; // 0, 10, 20, 30
msg.dynamic_seq().resize(3);
msg.dynamic_seq()[0] = 100;
msg.dynamic_seq()[1] = 200;
msg.dynamic_seq()[2] = 300;
writer->write(&msg);
std::cout << "已发送消息" << std::endl;
// 等待接收
for (int i = 0; i < 10 && !listener.received; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 清理
participant->delete_contained_entities();
DomainParticipantFactory::get_instance()->delete_participant(participant);
return listener.received ? 0 : -1;
}
编译与运行
- 使用
fastddsgen ArraySeq.idl生成辅助代码(含ArraySeqPubSubTypes.h/cpp)。 - 编译(以g++为例):
g++ -std=c++11 main.cpp ArraySeq.cxx ArraySeqPubSubTypes.cxx \
-I$FASTDDS_INCLUDE_DIR -L$FASTDDS_LIB_DIR \
-lfastdds -lfastcdr -o array_seq_demo
- 运行:
./array_seq_demo
验证方法
程序启动后,发布端发送一条消息,订阅端在同一进程内接收。观察标准输出:
已发送消息
收到消息: fixed_array = [0, 10, 20, 30], dynamic_seq = [100, 200, 300]
若输出与上述一致且进程退出码为0,则说明固定数组与可变序列均正确传输。若需跨进程验证,可将发布与订阅拆分为两个独立程序,分别运行于同一域(Domain ID=0)即可。
关键说明
- 固定数组在生成的C++类型中映射为
std::array<int32_t, 4>,通过msg.fixed_array()获取引用后按下标访问。 - 可变序列映射为
std::vector<int32_t>,使用前需resize()或push_back()分配长度。 - 本示例发布与订阅在同一进程,便于单文件验证;实际部署时两端可运行在不同主机,仅需保证Domain ID与Topic名称一致。