通信中间件 Fast DDS(三) :fastddsgen的安装与使用

目录

1.fastddsgen介绍

2.fastddsgen的安装

2.1.Java的环境安装

2.2.Maven的安装

2.3.fastddsgen安装

2.3.1.window的源码安装

2.3.2.windows使用vcpkg安装

2.3.3.Linux安装

3.fastddsgen的使用

[4.1.创建 IDL 文件](#4.1.创建 IDL 文件)

4.2.生成代码

4.3.生成的文件

4.5.常用命令选项

[4.6.复杂 IDL 示例](#4.6.复杂 IDL 示例)

[4.7.在 CMake 项目中集成](#4.7.在 CMake 项目中集成)

4.8.实际项目示例

4.9.故障排除

4.总结


1.fastddsgen介绍

fastddsgen 是 FastDDS 官方提供的 IDL(Interface Definition Language)编译器,用于将 IDL 定义的数据类型转换为 FastDDS 兼容的代码(支持 C++、Python 等语言),自动生成数据序列化 / 反序列化逻辑、类型注册代码等,是 FastDDS 开发的基础工具。

在 FastDDS 中,节点间通信的数据结构需通过 IDL 定义(类似接口契约或通信协议之类的),fastddsgen 的核心功能是:

  • 将 IDL 中的结构体(struct)、枚举(enum)等类型转换为目标语言的代码;
  • 自动生成数据的序列化(将数据转为字节流)和反序列化(将字节流还原为数据)逻辑;
  • 生成类型注册相关代码(让 FastDDS 识别自定义数据类型)。

举个例子,比如定义了如下数据结构:HelloWorld.idl

cpp 复制代码
struct HelloWorld
{
    unsigned long index;
    string message;
};

通过fastddsgen自动生成改数据结构的序列化和反序列化代码以及Fast DDS 兼容的发布者/订阅者代码,执行如下命令:

则会生成:

具体文件的作用会在后面章节详解。

2.fastddsgen的安装

fastddsgen 基于 Java 开发,需依赖 JDK 8+Maven(编译源码时需要)

2.1.Java的环境安装

JDK 8 及以上:fastddsgen 基于 Java 开发,需安装 JDK(推荐 OpenJDK 11)。

下载 OpenJDK 11 并安装,配置环境变量 JAVA_HOME(指向 JDK 安装目录),并将 %JAVA_HOME%\bin 添加到 PATH

具体的下载地址:https://adoptium.net/zh-CN/temurin/releases?version=11&os=any&arch=any

根据自己的系统下载合适的版本,我是在windows11系统上安装的,下载的是windows的安装程序OpenJDK11U-jdk_x64_windows_hotspot_11.0.28_6.msi

安装后此安装程序会把java的路径自动加到系统的环境变量中, 验证是否安装成功,在命令行执行:

2.2.Maven的安装

Maven的下载地址:

https://maven.apache.org/download.cgi

选择下面版本:

解压后配置 MAVEN_HOME 环境变量,将 %MAVEN_HOME%\bin 添加到 PATH一般需要安装在没有中文的目录下面:

验证 Maven 安装:

2.3.fastddsgen安装

2.3.1.window的源码安装

1.拉取 fastddsgen 源码

https://github.com/eProsima/Fast-DDS-Gen.git

2.编译构建

在fastddsgen的根目录下执行:

cpp 复制代码
./gradlew  assemble

但是在我的电脑上一直提示这个:

好像是下载gradle-7.6-bin.zip失败,尝试很多遍之后,把这个地址复制到浏览器看是否可以下载呢?结果可以,下载完gradle-7.6-bin.zip,但是在这里提示还是下载失败,怎么使用本地的gradle-7.6-bin.zip编译呢?于是想到:

fastddsgen 若在构建过程中依赖 Gradle(部分版本或子模块可能使用 Gradle 管理),且需要指定本地已下载的 gradle-7.6-bin.zip 避免重新下载,核心是利用 Gradle Wrapper 的本地缓存机制------ 将本地压缩包放入 Gradle 的分发缓存目录,Gradle 会自动识别并使用本地文件,无需重复下载。

具体步骤(Windows 系统为例)

1)找到 Gradle 分发缓存目录

Gradle Wrapper 会将下载的 Gradle 压缩包缓存到以下路径:

cpp 复制代码
C:\Users\<你的用户名>\.gradle\wrapper\dists\gradle-7.6-bin\<随机哈希目录>
  • <你的用户名>:即 Windows 登录用户名(如 Administrator 或你的账号名)。
  • <随机哈希目录>:Gradle 自动生成的唯一目录(如 xxxxxxxxx,由 Gradle 基于版本号计算,确保唯一性)。

我的电脑就是这个目录:

C:\Users\Administrator\.gradle\wrapper\dists\gradle-7.6-bin\9l9tetv7ltxvx3i8an4pb86ye

把刚下载好的gradle-7.6-bin.zip放到此目录下,重新执行构建命令:

然后把D:\OpenProject\Fast-DDS-Gen\scripts加到系统的环境变量中:

验证安装是否成功:

2.3.2.windows使用vcpkg安装

vcpkg install fastddsgen

2.3.3.Linux安装

方法1:从源码安装(推荐)

cpp 复制代码
# 克隆 Fast DDS 仓库
git clone https://github.com/eProsima/Fast-DDS-Gen.git
cd Fast-DDS

# 创建构建目录
mkdir build && cd build

# 配置和编译
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j$(nproc)

# 安装(包括 fastddsgen)
sudo make install

方法2:使用预编译二进制

cpp 复制代码
# Ubuntu/Debian
sudo apt update
sudo apt-get install fastddsgen

# 或者从 GitHub 发布页面下载
wget https://github.com/eProsima/Fast-DDS/releases/download/v2.10.0/fastddsgen-2.10.0-linux-x64.tar.gz
tar -xzf fastddsgen-2.10.0-linux-x64.tar.gz
sudo cp fastddsgen /usr/local/bin/

3.fastddsgen的使用

4.1.创建 IDL 文件

创建一个简单的 IDL 文件(如 HelloWorld.idl),定义通信的数据结构:

cpp 复制代码
struct HelloWorld
{
    unsigned long index;
    string message;
};

4.2.生成代码

cpp 复制代码
# 基本生成
fastddsgen HelloWorld.idl

# 生成并替换现有文件
fastddsgen -replace HelloWorld.idl

# 指定输出目录
fastddsgen -d generated HelloWorld.idl

# 生成示例代码
fastddsgen -example CMake HelloWorld.idl

在生成代码的过程中(windows11+vs2022),遇到一个问题:

cpp 复制代码
C:\Users\Administrator>fastddsgen  D:\OpenProject\Fast-DDS\examples\cpp\hello_tcp\Message.idl                           
Processing the file D:\OpenProject\Fast-DDS\examples\cpp\hello_tcp\Message.idl...                                       
ERROR<callPreprocessor>: Cannot execute the preprocessor. Reason: Cannot run program "cl.exe": CreateProcess error=2, 系统找不到指定的文件。

这个错误的原因是 fastddsgen 需要调用 C 预处理器(cl.exe) ,但系统中未找到该程序。cl.exe 是微软 Visual Studio 的 C/C++ 编译器,属于 Visual Studio 的 "C++ 生成工具" 组件,需安装并配置环境后才能使用。

解决方法1:用 Visual Studio 命令提示符运行 fastddsgen

cl.exe 的路径默认不会添加到系统全局 PATH 中,需通过 Visual Studio 自带的命令提示符 启动,该窗口会自动配置编译环境:

按下 Win 键,搜索并打开 "x64 Native Tools Command Prompt for VS 2022"(根据你的 VS 版本选择,如 2019/2022):

在该窗口中,重新执行你的 fastddsgen 命令:

cpp 复制代码
fastddsgen D:\OpenProject\Fast-DDS\examples\cpp\hello_tcp\HelloWorld.idl

解决方法2:(可选)手动添加 cl.exe 到系统 PATH(不推荐,易冲突)

若需在普通命令提示符中使用,可手动将 cl.exe 路径添加到系统 PATH

找到 cl.exe 的安装路径(根据 VS 版本和安装目录,示例路径):

cpp 复制代码
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x64

(路径中的 14.36.32532 是版本号,可能因安装版本不同而变化,可在 VC\Tools\MSVC 目录下查找最新版本)。

将该路径添加到系统 PATH 环境变量(步骤同之前环境变量配置)。

4.3.生成的文件

运行后会生成以下文件:

  • HelloWorld.hpp - 数据类型头文件

  • HelloWorldCdrAux.ipp和HelloWorldCdrAux.hpp - 数据打包实现

  • HelloWorldPubSubTypes.h - 发布/订阅类型支持头文件

  • HelloWorldPubSubTypes.cxx - 发布/订阅类型支持实现

  • HelloWorldTypeObjectSupport.hpp: 用于动态类型元数据的生成、序列化和验证

  • HelloWorldTypeObjectSupport.cxx: 用于动态类型元数据的生成、序列化和验证

4.5.常用命令选项

cpp 复制代码
# 显示帮助
fastddsgen -help

# 常用选项
fastddsgen -replace -d output_dir -typeobject MyTypes.idl

# 生成 CMake 项目示例
fastddsgen -example CMake -d examples ComplexType.idl

# 指定不同的编码
fastddsgen -encoding UTF8 MyTypes.idl

# 不生成已弃用的代码
fastddsgen -notypecode MyTypes.idl

完整选项列表:

选项 作用 示例
-h / --help 查看所有选项的帮助说明 fastddsgen -h
--version 查看 fastddsgen 版本 fastddsgen --version
-d <目录> 指定代码输出目录(默认当前目录) fastddsgen -d ./generated HelloWorld.idl
-replace 覆盖已存在的生成文件(默认不覆盖) fastddsgen -replace HelloWorld.idl
-language <语言> 指定生成代码的语言(默认 C++ fastddsgen -language Python HelloWorld.idl
-typeobject 生成动态类型(XTypes)支持文件(如 *TypeObjectSupport.* fastddsgen -typeobject HelloWorld.idl
-no-types 仅生成类型注册代码,不生成结构体定义(适合已有结构体时) fastddsgen -no-types HelloWorld.idl
-example <语言> 生成发布者 / 订阅者示例代码(支持 C++/Python fastddsgen -example C++ HelloWorld.idl
-topic <名称> 为示例代码指定 Topic 名称(默认用 IDL 结构体名) fastddsgen -example C++ -topic MyTopic HelloWorld.idl
-I <路径> 添加 IDL 包含文件的搜索路径(类似 C++ 的 -I fastddsgen -I ./include Common.idl
-D <宏定义> 定义预处理宏(类似 C++ 的 -D fastddsgen -D DEBUG HelloWorld.idl
-template <目录> 使用自定义代码生成模板(覆盖默认模板) fastddsgen -template ./my_templates HelloWorld.idl
-namespace <名称> 为生成的 C++ 代码指定命名空间(默认无) fastddsgen -namespace MyNS HelloWorld.idl
-cs 生成 C# 代码(实验性,需配合特定版本) fastddsgen -cs HelloWorld.idl
-java 生成java 代码 fastddsgen -java HelloWorld.idl

常用组合示例

1.生成 C++ 代码 + 示例到指定目录

cpp 复制代码
fastddsgen -d ./output -example C++ -topic HelloTopic HelloWorld.idl

效果:在 ./output 目录生成 HelloWorld 的结构体代码、类型注册代码,以及带 HelloTopic 主题的发布者 / 订阅者示例。

2.处理包含其他 IDL 的文件

HelloWorld.idl 中用 #include "Common.idl" 引用了其他 IDL,需指定包含路径:

cpp 复制代码
fastddsgen -I ./idl_include HelloWorld.idl

3.生成动态类型支持文件

cpp 复制代码
fastddsgen -typeobject -example C++ HelloWorld.idl

效果:除常规代码外,额外生成 HelloWorldTypeObjectSupport.hpp.cxx,支持动态类型发现。

4.6.复杂 IDL 示例

1.复杂数据类型 IDL

cpp 复制代码
module MyModule {
    
    // 枚举类型
    enum Color {
        RED,
        GREEN,
        BLUE
    };
    
    // 结构体包含数组和序列
    struct Vector3 {
        double x;
        double y;
        double z;
    };
    
    // 复杂结构体
    struct SensorData {
        unsigned long sensor_id;
        string sensor_name;
        Vector3 position;
        sequence<double> readings;
        Color led_color;
    };
    
    // 带键值的结构体(用于内容过滤)
    struct KeyedData {
        @key unsigned long id;
        string value;
        double timestamp;
    };
    
    // 联合类型
    union DataUnion switch (long) {
        case 0: long int_value;
        case 1: double double_value;
        case 2: string string_value;
        default: boolean bool_value;
    };
};

2.生成复杂类型

cpp 复制代码
fastddsgen -replace -d generated -typeobject ComplexTypes.idl

4.7.在 CMake 项目中集成

1.基本的 CMakeLists.txt

cpp 复制代码
cmake_minimum_required(VERSION 3.16)
project(MyFastDDSProject)

# 查找依赖
find_package(fastcdr REQUIRED)
find_package(fastrtps REQUIRED)
find_package(fastdds REQUIRED)

# 查找 fastddsgen
find_program(FASTDDSGEN fastddsgen)
if(NOT FASTDDSGEN)
    message(FATAL_ERROR "fastddsgen not found")
endif()

# 设置 IDL 文件
set(IDL_FILES
    HelloWorld.idl
    ComplexTypes.idl
)

# 生成代码
set(GENERATED_SOURCES "")
foreach(idl_file ${IDL_FILES})
    get_filename_component(target_name ${idl_file} NAME_WE)
    
    # 设置生成的文件路径
    set(gen_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
    set(gen_files 
        ${gen_dir}/${target_name}.h
        ${gen_dir}/${target_name}.cxx
        ${gen_dir}/${target_name}PubSubTypes.h
        ${gen_dir}/${target_name}PubSubTypes.cxx
    )
    
    # 添加自定义命令生成代码
    add_custom_command(
        OUTPUT ${gen_files}
        COMMAND ${FASTDDSGEN} -replace -d ${gen_dir} ${CMAKE_CURRENT_SOURCE_DIR}/${idl_file}
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${idl_file}
        COMMENT "Generating code for ${idl_file}"
    )
    
    list(APPEND GENERATED_SOURCES ${gen_files})
endforeach()

# 包含生成的头文件
include_directories(
    ${CMAKE_CURRENT_BINARY_DIR}/generated
    ${FASTCDR_INCLUDE_DIR}
    ${FASTRTPS_INCLUDE_DIRS}
)

# 创建可执行文件
add_executable(my_publisher
    src/publisher_main.cpp
    ${GENERATED_SOURCES}
)

add_executable(my_subscriber
    src/subscriber_main.cpp
    ${GENERATED_SOURCES}
)

# 链接库
target_link_libraries(my_publisher
    fastcdr
    fastrtps
    fastdds
)

target_link_libraries(my_subscriber
    fastcdr
    fastrtps
    fastdds
)

2.高级 CMake 集成

cpp 复制代码
# 自定义函数简化 IDL 生成
function(generate_dds_idl TARGET_NAME IDL_FILE)
    get_filename_component(name_we ${IDL_FILE} NAME_WE)
    set(gen_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
    
    set(gen_sources 
        ${gen_dir}/${name_we}.cxx
        ${gen_dir}/${name_we}PubSubTypes.cxx
    )
    
    set(gen_headers 
        ${gen_dir}/${name_we}.h
        ${gen_dir}/${name_we}PubSubTypes.h
    )
    
    add_custom_command(
        OUTPUT ${gen_sources} ${gen_headers}
        COMMAND ${FASTDDSGEN} -replace -d ${gen_dir} ${CMAKE_CURRENT_SOURCE_DIR}/${IDL_FILE}
        DEPENDS ${IDL_FILE}
        COMMENT "Generating DDS code from ${IDL_FILE}"
    )
    
    target_sources(${TARGET_NAME} PRIVATE ${gen_sources})
    target_include_directories(${TARGET_NAME} PRIVATE ${gen_dir})
endfunction()

# 使用示例
add_executable(my_app src/main.cpp)
generate_dds_idl(my_app HelloWorld.idl)
generate_dds_idl(my_app ComplexTypes.idl)

4.8.实际项目示例

1.项目结构

cpp 复制代码
my_project/
├── CMakeLists.txt
├── idl/
│   ├── HelloWorld.idl
│   └── SensorData.idl
├── src/
│   ├── publisher.cpp
│   ├── subscriber.cpp
│   └── main.cpp
└── generated/ (自动生成)

2.构建脚本

cpp 复制代码
#!/bin/bash
# build.sh

mkdir -p build
cd build

# 配置项目
cmake -DCMAKE_BUILD_TYPE=Release ..

# 编译
make -j$(nproc)

echo "构建完成!"

4.9.故障排除

1.fastddsgen 未找到

cpp 复制代码
# 解决方案:检查安装路径
which fastddsgen
# 或者
find /usr -name "fastddsgen" 2>/dev/null

2.IDL 语法错误

cpp 复制代码
# 验证 IDL 语法
fastddsgen -verbose MyTypes.idl

3.生成的代码编译错误

cpp 复制代码
# 确保 Fast DDS 版本匹配
fastddsgen -version
pkg-config --modversion fastdds

4.IDL文件编码

IDL 文件一般都使用 UTF-8 编码

4.总结

fastddsgen 是 FastDDS 开发的 "必经之路",正确使用它可以大幅减少手动编写序列化和类型注册代码的工作量。实际开发中,建议结合 -example 参数生成示例代码,快速搭建通信框架。

相关推荐
tt5555555555553 小时前
Linux 驱动开发与内核通信机制——超详细教程
linux·驱动开发·b树
tpoog3 小时前
[C++项目组件]Etcd的简单介绍和使用
开发语言·c++·etcd
shark_dev3 小时前
C/C++ 数据类型选择笔记:int、long long、char、string、float、double
c语言·c++
序属秋秋秋3 小时前
《C++进阶之C++11》【lambda表达式 + 包装器】
c++·笔记·学习·c++11·lambda表达式·包装器
程序设计实验室3 小时前
在Linux系统上一键配置DoH,解决DNS解析被污染
linux
关关长语3 小时前
Ubuntu 中获取指定软件依赖安装包
linux·运维·ubuntu
山,离天三尺三3 小时前
线程中互斥锁和读写锁相关区别应用示例
linux·c语言·开发语言·面试·职场和发展
dragon_cdut3 小时前
ubuntu22.04 无法清空回收站文件
linux·运维
七七七七073 小时前
【Linux 系统】进程优先级
linux·运维·服务器