1. 环境准备与源码编译第一次尝试在QT项目中集成fastDDS时我踩了不少坑。最头疼的就是源码编译环节网上能找到的教程要么太简略要么环境对不上。这里我整理了一份针对Windows平台MSVC2019的完整方案连新手也能轻松上手。fastDDS的源码编译需要提前准备好这些工具链Visual Studio 2019必须包含C桌面开发组件CMake 3.12以上版本建议用3.16Git for Windows用来拉取依赖项Python 3.7用于配置脚本具体操作时我推荐先用管理员权限打开x64 Native Tools Command Prompt for VS 2019然后按这个顺序执行git clone --recursive https://github.com/eProsima/Fast-DDS.git cd Fast-DDS mkdir build cd build cmake -DCMAKE_INSTALL_PREFIXC:\fastdds_install -DCMAKE_BUILD_TYPERelease .. cmake --build . --target install这里有个关键细节--recursive参数必须带上否则会漏掉foonathan_memory等关键子模块。编译过程大概需要15-30分钟取决于机器配置完成后会在C盘生成fastdds_install目录里面包含我们需要的include、lib和bin文件夹。2. QT项目配置实战2.1 qmake项目配置对于使用qmake的传统QT项目需要在.pro文件中添加这些关键配置。我建议新建一个专门存放第三方库的目录比如项目根目录下的3rdparty把fastDDS的include和lib文件夹拷贝进去。# 关键配置示例 QT core gui greaterThan(QT_MAJOR_VERSION, 4): QT widgets CONFIG c17 # 解决Windows平台常见符号冲突 win32 { QMAKE_CXXFLAGS_DEBUG -D_MBCS -D__DEBUG -DBOOST_ALL_DYN_LINK -D__LITTLE_ENDIAN__ -D_WIN32 QMAKE_CXXFLAGS_RELEASE -D_MBCS -DBOOST_ALL_DYN_LINK -D__LITTLE_ENDIAN__ -D_WIN32 QMAKE_LFLAGS /FORCE:MULTIPLE } # 头文件路径根据实际路径调整 INCLUDEPATH $$PWD/3rdparty/fastdds/include # 库文件路径 LIBS -L$$PWD/3rdparty/fastdds/lib win32:LIBS -lfoonathan_memory-0.7.1 -lfastcdr-1.0 -lfastrtps-2.8 win32:LIBS -lShlwapi -lIphlpapi -lws2_32 -lAdvapi32 win32:LIBS -llibssl64MD -llibcrypto64MD2.2 CMake项目配置现在越来越多的QT项目转向CMake配置方式略有不同。我在实际项目中发现CMake的配置更灵活但也更容易出错。下面这个模板经过多个项目验证cmake_minimum_required(VERSION 3.16) project(MyFastDDSProject) set(CMAKE_CXX_STANDARD 17) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) # 关键配置解决符号冲突 set(CMAKE_SHARED_LINKER_FLAGS /FORCE:MULTIPLE) # 假设fastDDS安装在C:/fastdds_install set(FASTDDS_DIR C:/fastdds_install) include_directories(${FASTDDS_DIR}/include) # 库文件路径 link_directories( ${FASTDDS_DIR}/lib ${FASTDDS_DIR}/lib/x64Win64VS2019 ${FASTDDS_DIR}/lib/x64Win64VS2019/VC ) find_package(Qt5 REQUIRED COMPONENTS Core Widgets) add_executable(${PROJECT_NAME} main.cpp MainWindow.cpp MainWindow.h MainWindow.ui ) target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Widgets foonathan_memory-0.7.1 fastcdr-1.0 fastrtps-2.8 Shlwapi Iphlpapi ws2_32 Advapi32 libssl64MD libcrypto64MD )3. 运行时环境部署编译通过只是第一步运行时才是真正的魔鬼关卡。根据我的踩坑经验90%的启动崩溃都源于DLL加载失败。必须确保这些文件在可执行文件的同级目录或系统PATH中fastDDS核心DLLfastcdr-1.0.dllfastrtps-2.8.dllfoonathan_memory-0.7.1.dllOpenSSL依赖项libssl64MD.dlllibcrypto64MD.dllWindows系统库Shlwapi.dllIphlpapi.dllws2_32.dll我建议在项目根目录创建deploy文件夹用这个批处理脚本自动拷贝所需DLLecho off set FASTDDS_BINC:\fastdds_install\bin set OPENSSL_BINC:\OpenSSL-Win64\bin set OUTPUT_DIR%~dp0deploy xcopy /Y %FASTDDS_BIN%\*.dll %OUTPUT_DIR% xcopy /Y %OPENSSL_BIN%\libssl64MD.dll %OUTPUT_DIR% xcopy /Y %OPENSSL_BIN%\libcrypto64MD.dll %OUTPUT_DIR%4. 常见问题解决方案4.1 符号重定义错误这是最典型的问题表现为LNK2005和LNK1169错误。根本原因是fastDDS和QT都使用了某些基础库的不同版本。除了前面提到的/FORCE:MULTIPLE链接选项还可以尝试在qmake中添加QMAKE_LFLAGS /IGNORE:4006,4221在CMake中添加set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4006,4221)4.2 内存分配冲突当同时使用fastDDS和QT容器时可能会遇到内存分配器冲突。解决方法是在main.cpp最开头添加#include foonathan/memory/container.hpp #include foonathan/memory/memory_pool.hpp #define FOONATHAN_MEMORY_POOL_IMPL(T) \ template class foonathan::memory::memory_poolfoonathan::memory::node_pool, T4.3 网络接口识别失败在部分Windows10/11系统上fastDDS可能无法正确识别网络接口。需要在创建Participant时显式指定#include fastdds/dds/domain/DomainParticipantFactory.hpp eprosima::fastdds::dds::DomainParticipantQos participant_qos; participant_qos.wire_protocol().builtin.avoid_builtin_multicast false; auto participant DomainParticipantFactory::get_instance()-create_participant(0, participant_qos);4.4 与QT事件循环集成在GUI程序中需要特别注意fastDDS的线程模型。我推荐使用QT的信号槽机制进行跨线程通信class MyPublisher : public QObject { Q_OBJECT public: explicit MyPublisher(QObject *parent nullptr) : QObject(parent) { publisher_ participant_-create_publisher(eprosima::fastdds::dds::PUBLISHER_QOS_DEFAULT); topic_ participant_-create_topic(MyTopic, MyDataType, eprosima::fastdds::dds::TOPIC_QOS_DEFAULT); writer_ publisher_-create_datawriter(topic_, eprosima::fastdds::dds::DATAWRITER_QOS_DEFAULT); } void publishData(const QByteArray data) { QMetaObject::invokeMethod(this, [this, data](){ void* sample nullptr; if (writer_-loan_sample(sample)) { memcpy(sample, data.constData(), data.size()); writer_-write(sample); } }); } signals: void newDataReceived(const QByteArray data); private: eprosima::fastdds::dds::DomainParticipant* participant_; eprosima::fastdds::dds::Publisher* publisher_; eprosima::fastdds::dds::Topic* topic_; eprosima::fastdds::dds::DataWriter* writer_; };