飞羽

fastdds在windows下的编译和使用
很久没更新了,由于本人工作原因以及个人原因(懒),现更新一个中间件编译和使用方法,以便以后进行翻阅。
扫描右侧二维码阅读全文
19
2025/07

fastdds在windows下的编译和使用

很久没更新了,由于本人工作原因以及个人原因(懒),现更新一个中间件编译和使用方法,以便以后进行翻阅。

fastdds源码编译

fastdds源码编译.jpg

一、fastdds介绍


fastDDS 是由OMG定义的数据分发服务(DDS)规范的 C++实现。fastdds库提供了应用程序编程接口(API)和通信协议,部署了以数据为中心的发布-订阅(DCPS)模型,旨在实现实时系统之间高效且可靠的信息分布。
DDS 采用的通信模型是一种多对多的单向数据交换,其中生成数据的应用程序将数据发布到属于消费数据应用程序的订阅者的本地缓存中。 信息流由负责数据交换的实体之间建立的服务质量 (QoS) 策略进行调节。
<来自官网翻译>
以下为DDS 数据流图,具体详细讲解请参考官网。
DDS 域内信息流动的概念图

二、FASTDDS编译

在windows中,你需要安装好visual studio,作者本人使用的visual studio版本为2019企业版,当前FASTDDS版本为3.3.0

  1. 第一步,克隆代码
git clone https://github.com/eProsima/Fast-DDS.git
cd Fast-DDS
git submodule update --init   #拉取子模块android,asio,fascdr,tinyxml2
git submodule add https://github.com/foonathan/memory.git thirdparty/foonathan-memory  #需要添加一个子模块
  1. 第二步,编译依赖库
    找到vs2019控制台(x64 Native Tools Command Prompt for VS 2019),打开,以下编译过程需要在vs2019控制台中操作,如下图

控制台

2.1 编译 foonathan-memory

cd thirdparty/foonathan-memory #进入foonathan-memory目录
mkdir build
cd build #构建build目录
cmake ../ -DFOONATHAN_MEMORY_BUILD_EXAMPLES=OFF -DFOONATHAN_MEMORY_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=F:\fastdds\cmake\Fast-DDS\thirdparty\install #指定安装目录和配置foonathan-memory相关功能
cmake --build . --target install --config Release #在vs2019下

执行完毕后foonathan-memory安装在F:fastddscmakeFast-DDSthirdpartyinstall目录。

2.2 编译 fastcdr
编译fastcdr与编译foonathan-memory类似,这里就不多赘述了。

cd ../..
cd fastcdr
mkdir build
cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=F:\fastdds\cmake\Fast-DDS\thirdparty\install 
cmake --build . --target install --config Release

2.3 编译 tinyxml2

编译tinyxml2与编译foonathan-memory类似,同样不多赘述了。

cd ../..
cd tinyxml2
mkdir build
cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=F:\fastdds\cmake\Fast-DDS\thirdparty\install
cmake --build . --target install --config Release

2.3 编译 Fast-DDS
编译Fast-DDS需要指定上述第三方库的安装位置和asio,然后进行编译。

cd ../../../../
cd Fast-DDS
mkdir build
cd build
cmake ../  -DCMAKE_INSTALL_PREFIX=F:\fastdds\cmake\Fast-DDS\install     -DCMAKE_PREFIX_PATH="F:\fastdds\cmake\Fast-DDS\thirdparty\asio\asio;F:\fastdds\cmake\Fast-DDS\thirdparty\install" -DNO_TLS=ON -DCOMPILE_EXAMPLES=ON
cmake --build . --target install --config Release

如下图为编译后第三方库目录结构:
第三方库目录结构
如下图为编译后FASTDDS目录结构<未截全>:
FASTDDS目录结构
在bin目录下,生成以下文件:
fastdds编译结果

就此,编译成功

  1. 使用方法
    3.1 编写IDL文件,以hello world为例(helloworld.idl):
module HelloWorldModule {

struct HelloWorld
{
    unsigned long index;
    string message;
};

};

helloworld.idl

3.2 IDL生成
使用fastddsgen.bat进行代码生成

fastddsgen.bat helloworld.idl -d hello/ -language c++

生成后截图:
生成后截图

三、fastdds使用

3.3 工程使用
在vs2019中新建工程,引入头文件和cpp文件,如下图所示:
工程目录

3.4 配置预处理器
需要你在工程,属性C/C++选项,预处理器选项卡,预处理器定义中添加以下内容,告诉编译器使用 Fast CDR和FASTDDS 的动态链接版本:

FASTCDR_DYN_LINK
FASTDDS_DYN_LINK

截图如下:
配置预处理器截图

3.5 添加订阅者
在工程中添加订阅者代码

#include <chrono>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <thread>

#include "helloworldPubSubTypes.hpp"

using namespace eprosima::fastdds::dds;
using namespace HelloWorldModule;

class HelloWorldPublisher {
private:
    HelloWorld hello_;

    DomainParticipant* participant_;

    Publisher* publisher_;

    Topic* topic_;

    DataWriter* writer_;

    TypeSupport type_;

    class PubListener : public DataWriterListener {
    public:
        PubListener() : matched_(0) {}

        ~PubListener() override {}

        void on_publication_matched(DataWriter*, const PublicationMatchedStatus& info) override {
            if (info.current_count_change == 1) {
                matched_ = info.total_count;
                std::cout << "Publisher matched." << std::endl;
            }
            else if (info.current_count_change == -1) {
                matched_ = info.total_count;
                std::cout << "Publisher unmatched." << std::endl;
            }
            else {
                std::cout << info.current_count_change
                    << " is not a valid value for PublicationMatchedStatus current count change." << std::endl;
            }
        }

        std::atomic_int matched_;

    } listener_;

public:
    HelloWorldPublisher()
        : participant_(nullptr),
        publisher_(nullptr),
        topic_(nullptr),
        writer_(nullptr),
        type_(new HelloWorldPubSubType()) {}

    virtual ~HelloWorldPublisher() {
        if (writer_ != nullptr) {
            publisher_->delete_datawriter(writer_);
        }
        if (publisher_ != nullptr) {
            participant_->delete_publisher(publisher_);
        }
        if (topic_ != nullptr) {
            participant_->delete_topic(topic_);
        }
        DomainParticipantFactory::get_instance()->delete_participant(participant_);
    }

    //! Initialize the publisher
    bool init() {
        hello_.index(0);
        hello_.message("HelloWorld");

        DomainParticipantQos participantQos;
        participantQos.name("Participant_publisher");
        participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
        if (participant_ == nullptr) {
            std::cout << "Error creating participant." << std::endl;
            return false;
        }

        // Register the Type
        type_.register_type(participant_);

        // Create the publications Topic
        topic_ = participant_->create_topic("HelloWorldTopic1", type_.get_type_name(), TOPIC_QOS_DEFAULT);
        if (topic_ == nullptr) {
            std::cout << "Error creating topic." << std::endl;
            return false;
        }

        // Create the Publisher
        publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);
        if (publisher_ == nullptr) {
            std::cout << "Error creating publisher." << std::endl;
            return false;
        }

        // Create the DataWriter
        writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_);
        if (writer_ == nullptr) {
            std::cout << "Error creating writer." << std::endl;
            return false;
        }
        return true;
    }

    //! Send a publication
    bool publish() {
        if (listener_.matched_ > 0) {
            hello_.index(hello_.index() + 1);
            writer_->write(&hello_);
            return true;
        }
        return false;
    }

    //! Run the Publisher
    void run(uint32_t samples) {
        uint32_t samples_sent = 0;
        while (true) {
            if (publish()) {
                samples_sent++;
                std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() << " SENT" << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
};

int main(int argc, char** argv) {
    std::cout << "Starting publisher." << std::endl;
    uint32_t samples = 10;

    HelloWorldPublisher* mypub = new HelloWorldPublisher();
    if (mypub->init()) {
        mypub->run(samples);
    }

    delete mypub;
    return 0;
}

编译,不出意外订阅者编译成功。

3.6 添加发布者
在工程中添加发布者代码

#include <chrono>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <thread>

#include "helloworldPubSubTypes.hpp"

using namespace eprosima::fastdds::dds;
using namespace HelloWorldModule;

class HelloWorldPublisher {
private:
    HelloWorld hello_;

    DomainParticipant* participant_;

    Publisher* publisher_;

    Topic* topic_;

    DataWriter* writer_;

    TypeSupport type_;

    class PubListener : public DataWriterListener {
    public:
        PubListener() : matched_(0) {}

        ~PubListener() override {}

        void on_publication_matched(DataWriter*, const PublicationMatchedStatus& info) override {
            if (info.current_count_change == 1) {
                matched_ = info.total_count;
                std::cout << "Publisher matched." << std::endl;
            }
            else if (info.current_count_change == -1) {
                matched_ = info.total_count;
                std::cout << "Publisher unmatched." << std::endl;
            }
            else {
                std::cout << info.current_count_change
                    << " is not a valid value for PublicationMatchedStatus current count change." << std::endl;
            }
        }

        std::atomic_int matched_;

    } listener_;

public:
    HelloWorldPublisher()
        : participant_(nullptr),
        publisher_(nullptr),
        topic_(nullptr),
        writer_(nullptr),
        type_(new HelloWorldPubSubType()) {}

    virtual ~HelloWorldPublisher() {
        if (writer_ != nullptr) {
            publisher_->delete_datawriter(writer_);
        }
        if (publisher_ != nullptr) {
            participant_->delete_publisher(publisher_);
        }
        if (topic_ != nullptr) {
            participant_->delete_topic(topic_);
        }
        DomainParticipantFactory::get_instance()->delete_participant(participant_);
    }

    //! Initialize the publisher
    bool init() {
        hello_.index(0);
        hello_.message("HelloWorld");

        DomainParticipantQos participantQos;
        participantQos.name("Participant_publisher");
        participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
        if (participant_ == nullptr) {
            std::cout << "Error creating participant." << std::endl;
            return false;
        }

        // Register the Type
        type_.register_type(participant_);

        // Create the publications Topic
        topic_ = participant_->create_topic("HelloWorldTopic1", type_.get_type_name(), TOPIC_QOS_DEFAULT);
        if (topic_ == nullptr) {
            std::cout << "Error creating topic." << std::endl;
            return false;
        }

        // Create the Publisher
        publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);
        if (publisher_ == nullptr) {
            std::cout << "Error creating publisher." << std::endl;
            return false;
        }

        // Create the DataWriter
        writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_);
        if (writer_ == nullptr) {
            std::cout << "Error creating writer." << std::endl;
            return false;
        }
        return true;
    }

    //! Send a publication
    bool publish() {
        if (listener_.matched_ > 0) {
            hello_.index(hello_.index() + 1);
            writer_->write(&hello_);
            return true;
        }
        return false;
    }

    //! Run the Publisher
    void run(uint32_t samples) {
        uint32_t samples_sent = 0;
        while (true) {
            if (publish()) {
                samples_sent++;
                std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() << " SENT" << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
};

int main(int argc, char** argv) {
    std::cout << "Starting publisher." << std::endl;
    uint32_t samples = 10;

    HelloWorldPublisher* mypub = new HelloWorldPublisher();
    if (mypub->init()) {
        mypub->run(samples);
    }

    delete mypub;
    return 0;
}

编译,不出意外,发布者编译成功

四、运行截图

左边为订阅者,右侧为发布者。

运行截图

文章名: 《fastdds在windows下的编译和使用》

文章链接:https://blog.8086k.cn/archives/147/

联系方式:1412981048@qq.com

除特别注明外,文章均为飞羽小随笔原创,转载时请注明本文出处及文章链接
Last modification:July 19th, 2025 at 01:46 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment