服务器上安装虚拟机以及编译FastDDS以及ShapesDemo开源项目

news2025/1/10 16:43:57

🥁作者: 华丞臧
📕​​​​专栏:【C++】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。

推荐一款刷题网站 👉LeetCode


文章目录

  • 前言
  • 一、虚拟机的安装
    • 1.1 安装ubuntu虚拟机
    • 1.2 网络配置
    • 1.3 kvm软件部分指令
  • 二、FastDDS开源项目
    • 2.1 FastDDS介绍
      • 2.1.1 什么是DDS
      • 2.1.2 DCPS模型
      • 2.1.3 RTPS协议
    • 2.2 FastDDS的安装及编译
      • 2.2.1 FastDDS安装
      • 2.2.2 工具需求
      • 2.2.3 依赖项
      • 2.2.4 本地安装*eProsima Fast DDS*
      • 2.2.5 样例测试
        • CMakeLists.txt文件解读
  • 三、ShapesDemo安装及编译
    • 3.1 什么是ShapesDemo?
    • 3.2 ShapesDemo安装
      • 3.2.1 从源码安装到ubuntu
      • 3.2.2 形状演示
  • 四、扩展
    • 4.1 Fast-DDS-Gen
      • 4.1.1 依赖项
      • 4.1.2 编译Fast-DDS-Gen
      • 4.1.3 测试
    • 4.2 XML配置文件
    • 4.3 Dynamic


前言

本文章主要介绍三个任务,一是在服务器上安装一个自己的ubuntu虚拟机;二是在ubuntu虚拟机上编译开源项目FastDDS;三是编译FastDDS的ShapesDemo。本文安装虚拟机、编译FastDDS以及ShapesDemo使用的都是ubuntu虚拟机,镜像为ubuntu-20.04.6-live-server-amd64.iso。

一、虚拟机的安装

1.1 安装ubuntu虚拟机

通过查阅资料,我了解到服务器上安装虚拟机可以使用kvm软件,使用下面的指令可以安装kvm软件及其依赖项:

yum -y install  qemu-kvm libvirt libvirt-python libguestfs-tools virt-install virt-clone virt-v2v virt-manager virt-viewer

创建虚拟机,首先需要一个磁盘镜像文件,这里使用qemu-img来创建,指令如下:

qemu-img create -f qcow2 vm01.qcow2 20G # 新建磁盘镜像文件 

有了磁盘镜像文件就可以开始创建虚拟机了,我采用命令行式创建虚拟机,使用ubuntu-20.04.6-live-server-amd64.iso镜像,指令如下:

virt-install --virt-type=kvm --name=ub01 --vcpus=36 --memory=73728 
--location /home/iso/ubuntu-20.04.6-live-server-amd64.iso,
kernel=casper/vmlinuz,initrd=casper/initrd 
--disk path=/home/imags/zch/vm01.qcow2,size=80,format=qcow2 
--network bridge=br0 --graphics none --extra-args='console=ttyS0'  --force

虚拟机创建好之后会进入安装界面,设置好用户和密码就可以开始使用ubuntu虚拟机了。

1.2 网络配置

创建好并进入虚拟机后,网络是不可用的,我们可以通过配置/etc/netplan/00-installer-config.yaml文件使网络可用,配置文件内容如下:

# This is the network config written by 'subiquity'
network:
  ethernets:
    ens2:
      addresses: [192.168.2.225/24] # 与宿主机在同一网段即可
      gateway4: 192.168.2.1
      dhcp4: false
      optional: true
      nameservers: 
        addresses: [192.168.2.1, 8.8.8.8]
  version: 2
  renderer: networkd

文件配置好后,输入sudo netplan apply指令使配置生效,即可使用网络。

1.3 kvm软件部分指令

virsh list --all 		# 显示所有已经定义的虚拟机的状态信息
virsh start ub01     	# 启动名为ub01虚拟机
virsh console ub01   	# 连接名为ub01虚拟机
virsh shutdown ub01   	# 关闭名为ub01虚拟机
virsh destroy ub01   	# 摧毁名为ub01虚拟机
virsh undefine ub01   	# 删除名为ub01虚拟机

二、FastDDS开源项目

2.1 FastDDS介绍

2.1.1 什么是DDS

数据分发服务 (DDS) 是一种以数据为中心的通信协议,用于分布式软件应用程序通信。它描述了支持数据提供程序和数据使用者之间通信的通信应用程序编程接口 (API) 和通信语义。

由于它是以数据为中心的发布订阅 (DCPS) 模型,因此在其实现中定义了三个关键应用程序实体:发布实体,用于定义信息生成对象及其属性;订阅实体,定义信息消耗对象及其属性;以及定义作为主题传输的信息类型的配置实体,并使用其服务质量 (QoS) 属性创建发布者和订阅者,以确保上述实体的正确性能。

简单来说DDS就是一种以数据为中心的通信协议,用于分布式软件应用程序通信。而FastDDS一个基于DDS标准实现的开源库,是FastRTPS库的升级版本,为DDS标准提供高性能和可扩展性的实现。

2.1.2 DCPS模型

在DCPS模型中主要有四个基本元素:

  • 发布者(Publisher):负责创建和配置其实现的DataWriters的 DCPS 实体。DataWriters是负责实际发布消息的实体。每个主题都有一个分配的Topic,用于发布消息。
  • 订阅者(Subscriber):DCPS实体负责接收在其订阅的主题下发布的数据。它提供一个或多个 DataReader 对象,这些对象负责将新数据的可用性传达给应用程序。
  • 话题(Topic):它是绑定发布和订阅的实体。它在 DDS 域中是唯一的。通过TopicDescription,它允许发布和订阅的数据类型的统一性。
  • 域(Domain):这是用于链接属于一个或多个应用程序的所有发布者和订阅者的概念,这些发布者和订阅者在不同主题下交换数据。这些参与域的单个应用程序称为DomainParticipant

DDS 域由域 ID 标识。域参与者定义域 ID 以指定其所属的 DDS 域。具有不同 ID 的两个域参与者不知道彼此在网络中的存在。因此,可以创建多个通信渠道。这适用于涉及多个 DDS 应用程序,其各自的域参与者相互通信的场景,但这些应用程序不得干扰。DomainParticipant充当其他 DCPS 实体的容器,充当PublisherSubscriber和Topic实体的工厂,并在域中提供管理服务。

在这里插入图片描述

2.1.3 RTPS协议

实时发布订阅(RTPS)协议是为支持DDS而开发的,是一种发布订阅同行中间件,通信功能强大,支持UDP/IP、TCP以及共享内存(SHM)。
在这里插入图片描述
RTPS中定义了域的概念,它定义了一个单独的通信平面。多个域可以同时并存,域中可以包含任意数量的RTPSParticipants,即能够发送接收数据的元素。RTPSParticipants有两种端点:

  • RTPSWriter:发送数据
  • RTPSReader:接收数据

RTPSParticipant中可以有任意数量的发送和接收的端点。他们通过围绕Topic展开,Topic定义和标记正在交换的数据,参与者通过RTPSWriter将数据写入Topic,也可以通过RTPSReader来接收与订阅相关的数据。
在这里插入图片描述

2.2 FastDDS的安装及编译

2.2.1 FastDDS安装

FastDDS官方给出了三种方式安装,我使用从源代码安装FastDDS库到Linux的方式。从源代码在 Linux 环境中安装 eProsima Fast DDS,将安装以下软件包:

  • foonathan_memory_vendor,一个与 STL 兼容的C++内存分配器库。
  • fastcdr,一个根据标准 CDR 序列化机制进行序列化的C++库。
  • fastrtpseProsima Fast DDS库的核心库。

2.2.2 工具需求

安装过程中所需要的工具如下:

  • CMake, g++, pip3, wget 和 git

使用下面的指令安装所需工具:

sudo apt install cmake g++ python3-pip wget git

2.2.3 依赖项

eProsima Fast DDS 在从 Linux 环境中的源代码安装时必须具有以下依赖项:

  • Asio 和 TinyXML2 库

    sudo apt install libasio-dev libtinyxml2-dev
    
  • OpenSSL

    sudo apt install libssl-dev
    
  • Libp11 和 SoftHSM 库

    sudo apt install libp11-dev libengine-pkcs11-openssl
    
    sudo apt install softhsm2
    # 请注意,softhsm2 软件包会创建一个名为 softhsm 的新组。要授予对 HSM 模块的访问权限,用户必须属于此组
    sudo usermod -a -G softhsm 用户名
    

具体安装方法参考eProsima Fast DDS

2.2.4 本地安装eProsima Fast DDS

创建一个目录用来下载和构建eProsima Fast DDS及其依赖项:

mkdir Fast-DDS

克隆以下依赖项并用cmake编译:

  • 安装fastrtps

    # 安装colcon和vcstool
    pip3 install -U colcon-common-extensions vcstool  
        
    # 下载安装fastrtps
    cd ~/Fast-DDS
    wget https://raw.githubusercontent.com/eProsima/Fast-DDS/master/fastrtps.repos
    mkdir src
    vcs import src < fastrtps.repos
    # 如果vcs找不到可以运行下面的指令
    ~/.local/bin/vcs import src < fastrtps.repos
        
    # 构建包    
    colcon build  
    # 如果colcon找不到   
    ~/.local/bin/colcon build
    
    # 本地准备环境
    source ~/Fast-DDS/install/setup.bash  
    # 或者
    echo 'source ~/Fast-DDS/install/setup.bash' >> ~/.bashrc
    
  • 安装foonathan_memory_vendor

    cd ~/Fast-DDS
    git clone https://github.com/eProsima/foonathan_memory_vendor.git
    mkdir foonathan_memory_vendor/build
    cd foonathan_memory_vendor/build
    cmake .. -DCMAKE_INSTALL_PREFIX=~/Fast-DDS/install -DBUILD_SHARED_LIBS=ON
    cmake --build . --target install
    
  • 安装Fast-CDR

    cd ~/Fast-DDS
    git clone https://github.com/eProsima/Fast-CDR.git
    mkdir Fast-CDR/build
    cd Fast-CDR/build
    cmake .. -DCMAKE_INSTALL_PREFIX=~/Fast-DDS/install
    cmake --build . --target install
    

安装好上述依赖项就可以安装eProsima Fast-DDS

cd ~/Fast-DDS
git clone https://github.com/eProsima/Fast-DDS.git
mkdir Fast-DDS/build
cd Fast-DDS/build
cmake ..  -DCMAKE_INSTALL_PREFIX=~/Fast-DDS/install
cmake --build . --target install

2.2.5 样例测试

在~/FastDDS中创建一个文件夹demo用来跑测试样例:

cd ~/Fast-DDS
mkdir demo && cd demo
# 也可以不用克隆,在安装fastdds中可以找到DynamicHelloWorldExample,路径为Fast-DDS/examples/cpp/dds
git clone https://github.com/eProsima/FastDDS/tree/master/examples/cpp/dds/DynamicHelloWorldExample
mkdir build && cd build
cmake ..

CMakeLists.txt文件解读

# 说明cmake最低版本要求
cmake_minimum_required(VERSION 3.16.3) 

# 定义项目名称为DDSHelloWorldExample,指定版本号和编程语言C++
project(DDSHelloWorldExample VERSION 1 LANGUAGES CXX) 

# 查找依赖项
if(NOT fastcdr_FOUND)
    find_package(fastcdr REQUIRED) # 如果没找到使用find_package命令来查找
endif()

if(NOT fastrtps_FOUND)
    find_package(fastrtps REQUIRED)
endif()

# 检查编译器是否支持C++11标准
include(CheckCXXCompilerFlag)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    check_cxx_compiler_flag(-std=c++11 SUPPORTS_CXX11)
    if(NOT SUPPORTS_CXX11)
        message(FATAL_ERROR "Compiler doesn't support C++11")
    endif()
endif()

message(STATUS "Configuring HelloWorld example...") 	# 输出信息
file(GLOB DDS_HELLOWORLD_EXAMPLE_SOURCES_CXX "*.cxx")	# 定义一个变量表示"*.cxx"
file(GLOB DDS_HELLOWORLD_EXAMPLE_SOURCES_CPP "*.cpp")	# 定义一个变量表示"*.cpp"

# 使用${}依赖项生成DDSHelloWorldExample可执行文件
add_executable(DDSHelloWorldExample ${DDS_HELLOWORLD_EXAMPLE_SOURCES_CXX} ${DDS_HELLOWORLD_EXAMPLE_SOURCES_CPP}) 
# 为可执行文件添加编译定义选项
target_compile_definitions(DDSHelloWorldExample PRIVATE
    $<$<AND:$<NOT:$<BOOL:${WIN32}>>,$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">>:__DEBUG>
    $<$<BOOL:${INTERNAL_DEBUG}>:__INTERNALDEBUG> # Internal debug activated.
)
# 可执行文件链接库
target_link_libraries(DDSHelloWorldExample fastrtps fastcdr fastdds::optionparser)
# 将DDSHelloWorldExample安装到指定路径
install(TARGETS DDSHelloWorldExample
    RUNTIME DESTINATION examples/cpp/dds/HelloWorldExample/${BIN_INSTALL_DIR}) 

编译完成HelloWorldExample后,在build文件夹中找到DDSHelloWordExample可执行程序,在虚拟机上运行两个程序,如下:

./DDSHelloWordExample publisher
./DDSHelloWordExample subscriber

我们可以在不同主机(服务器)上安装同样的样例程序来测试,也可以在同一台服务器上不同的虚拟机上测试。下图是在同一服务器的不同虚拟机上进行测试的结果:
在这里插入图片描述

三、ShapesDemo安装及编译

3.1 什么是ShapesDemo?

ShapesDemo是一个常见的示例程序,用于演示分布式系统中使用DDS(Data Distribution Service)实现数据发布和订阅的过程。

该示例程序通常以图形形状(如圆、矩形、三角形等)为数据对象,展示了如何在发布者和订阅者之间进行实时数据的传输和交互。

ShapesDemo示例中,通常会有两个主要组件:

  1. 发布者(Publisher):发布者负责创建并发送图形形状的数据,将其发布到DDS中。它可以定义不同类型的图形形状对象,并定期更新这些对象的状态。发布者还负责在DDS网络中注册和广播所发布的数据。
  2. 订阅者(Subscriber):订阅者订阅感兴趣的图形形状数据,并接收来自发布者的更新信息。它可以订阅特定类型的图形形状或所有类型的数据。订阅者从DDS中接收到发布者发送的数据,并对其进行处理、显示或执行其他操作。

通过运行ShapesDemo示例程序,我们能够观察到发布者创建图形形状对象并发送数据,而订阅者接收并处理这些数据的过程。这有助于理解DDS在实时数据传输中的工作原理以及如何使用DDS实现分布式系统中的数据发布和订阅功能。

3.2 ShapesDemo安装

ShapesDemo即形状演示,可以理解为用图形演示。Fast-DDS的ShapesDemo就是用图形来演示Fast-DDS,让我们能够以更加形象直观的理解FastDDS。

3.2.1 从源码安装到ubuntu

安装ShapesDemo前,用户必须确保ubuntu上Qt5,可以在终端上运行一下指令来安装:

sudo apt install -y qtbase5-dev

可以使用colcon安装ShapesDemo,首先安装colcon和vcs,安装指令如下:

pip install -U colcon-common-extensions vcstool

创建一个ShapesDemo文件夹用来下载安装eProsima Shapes Demo 及其依赖项的存储库文件,步骤如下:

mkdir -p ShapesDemo/src && cd ShapesDemo
wget https://raw.githubusercontent.com/eProsima/ShapesDemo/master/shapes-demo.repos
vcs import src < shapes-demo.repos
# 找不到vcs,尝试使用下面的指令
~/.local/bin/vcs import src < shapes-demo.repos

# 构建包
colcon build
# 找不到colcon,尝试使用下面的指令
~/.local/bin/colcon build

链接应用程序可执行文件以使其可从当前目录访问:

source install/setup.bash

运行ShapesDemo:

ShapesDemo

3.2.2 形状演示

使用服务器上的虚拟机,用xshell连接的服务器,而xshell并不支持弹窗,ShapesDemo运行会弹出一个窗口用来做形状演示。我这里使用的是Xmanager软件来支持ShapesDemo,使用Xmanager配置步骤如下:

  • 创建一个XDMCP会话,配置如下,其中主机为虚拟机ip地址。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gY3Re90-1688115349978)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230629142524634.png)]

  • 配置DISPLAY环境变量

    export DISPLAY=192.168.3.240:0.0 #此ip为使用的电脑ip
    # 注意如果使用同一台主机上的两个虚拟机来演示,其中一个DISPLAY配置如下
    export DISPLAY=192.168.3.240:1.0 
    

ShapesDemo运行结果如下:
在这里插入图片描述

四、扩展

4.1 Fast-DDS-Gen

Fast-DDS-Gen是使用Gradle构建的,Gradle是一个开源的构建自动化工具,需要执行Java版本。FasT-DDS-Gen是一个代码生成工具,用于根据DDS标准规范生成相关的代码。它使用IDL描述数据类型和通信接口,并根据IDL文件生成相应的数据类型定义、消息传输代码和序列化/反序列化代码等。

4.1.1 依赖项

  • 安装Java JDK

    sudo apt install openjdk-11-jdk
    

4.1.2 编译Fast-DDS-Gen

cd ~
git clone --recursive https://github.com/eProsima/Fast-DDS-Gen.git
cd Fast-DDS-Gen
./gradlew assemble

4.1.3 测试

首先我们要编写一个IDL文件,内容如下:

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

编写并保存好IDL文件,接下来就可以使用Fast-DDS-Gen工具来生成代码了,运行下面的指令:

<path-to-Fast-DDS-Gen>/scripts/fastddsgen -example CMake Test.idl

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xszI9a6X-1688115349979)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230629171343051.png)]

代码生成完我们可以来测试这些代码,运行下面的指令:

mkdir build && cd build
cmake ..
make

结果如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0F4MghdW-1688115349980)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230629173210920.png)]

4.2 XML配置文件

使用fastddsgen和idl文件可以自动帮我们生成主体代码。但当需要使用一个新的类型时,我们每次都需要新建一个idl文件并使用fastddsgen工具来生成代码。使用XML配置文件,我们就可以直接在XML文件中添加我们所需要的类型即可进行使用,不用fastddsgen工具来生成代码。

XML配置文件是一种常见的用于配置应用程序或系统的文件格式。它使用XML(可扩展标记语言)的语法,以层次结构的方式组织和描述配置信息。XML文件中类型配置文件的定义是标签式的,每个元素可以包含一个或多个类型定义。在一个元素中定义多个类型或为每个元素定义单个类型具有相同的结果。

  • XML可用基本类型的标识符

    booleanchar8char16
    byteoctetuint8
    int8int16int32
    uint16uint32int64
    uint64float32float64
    float128stringwstring
  • XML配置文件实例:

    <?xml version="1.0" encoding="UTF-8" ?>  # XML声明,指定XML版本和字符编码
    <types xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" > #使用网址标识的命名空间
    	<type> # 类型元素
    		<struct name="HelloWorld">   # 创捷结构体,名为HelloWorld
    			<member name="message" type="string"/>  # 结构体成员变量
    			<member name="index" type="uint32"/>
    			<member name="array" type="uint32" arrayDimensions="5,2"/> # 5*2的数组
    		</struct> # 结构体结束标志
    	</type> # 类型结束标志
    	
    	<type>
    		<struct name="Test">
    			<member name="message" type="string"/>
    			<member name="index" type="uint32"/>
    		</struct>	    
    	</type>
    </types>
    

使用fastddsgen和IDL与使用XML配置文件相比,前者会用IDL结构体生成一个类,同时声明定义其数据类型封装结构体;后者不需要封装目标结构体并声明定义,eProsima Fast DDS中提供了一些接口用来获取目标结构以及其成员变量、定义对象等,下面代码是一段实例:

// 加载目标xml文件,并判断是否加载成功
if (eprosima::fastrtps::xmlparser::XMLP_ret::XML_OK !=           eprosima::fastrtps::xmlparser::XMLProfileManager::loadXMLFile("helloworld_example_type_profile.xml"))
    { // 加载失败
        std::cout <<
            "Cannot open XML file \"helloworld_example_type_profile.xml\". Please, run the publisher from the folder "
                  << "that contatins this XML file." << std::endl;
        return false;
    }

// 获取动态数据类型Test,并用build构建该类型对象
eprosima::fastrtps::types::DynamicType_ptr dyn_type =
          eprosima::fastrtps::xmlparser::XMLProfileManager::getDynamicTypeByName("Test")->build(); 
	// 使用动态类型创建TypeSupport
    TypeSupport m_type(new eprosima::fastrtps::types::DynamicPubSubType(dyn_type));
	// 创建动态数据对象
    m_Hello = eprosima::fastrtps::types::DynamicDataFactory::get_instance()->create_data(dyn_type); 
	//m_Hello->set_string_value("hello", 0); // 两个参数:value  id(id与XML文件中定义成员的顺序相关)
    m_Hello->set_uint32_value(0, 1);

使用XML配置文件,我们就只需要完成发布者、订阅者、主函数代码的编写即可。具体实例代码请看
在这里插入图片描述XMLFastDDSExample

  • 当我在三个虚拟机上测试代码时,结果如下:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4u742Jki-1688115349981)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230630151502225.png)]

4.3 Dynamic

eProsima Fast DDS还提供了一种动态定义的方式,这种方式让我们可以不用依赖代码文件以外的文件来定义所需要的结构。eProsima Fast 提供了一些接口在代码中来定义结构体数据类型,我们可以用这些接口定义自己所需要的数据类型。
下面是一段代码实例:

void DynamicDataPublisher::publishData()
{
    static long long i = 0;
    std::cout << "第" << std::to_string(i) << "次更新数据" << std::endl;
    //  根据动态类型构建对象
    auto struct_data =
        DynamicDataFactory::get_instance()->create_data(dynamic_struct_ptr_);
    assert(struct_data != nullptr);
	// 设置结构体的值
    assert(struct_data->set_byte_value(i % 127, 0) == ReturnCode_t::RETCODE_OK);
    assert(struct_data->set_int32_value(i % (0xffffffff / 2 - 1), 1) ==
           ReturnCode_t::RETCODE_OK);
    assert(
        struct_data->set_string_value(std::string("seq:") + std::to_string(i),
                                      2) == ReturnCode_t::RETCODE_OK);
    std::cout << "数据为:" << i % 127 << "  " << i % (0xffffffff / 2 - 1)
              << "  " << std::string("seq:") + std::to_string(i) << "  "
              << std::endl;

    data_writer_->write(struct_data);
    ++i;
}

void DynamicDataPublisher::create_dynamic_struct_type()
{
    // 创建byte类型构建器
    DynamicTypeBuilder_ptr base_type_builder =
        DynamicTypeBuilderFactory::get_instance()->create_byte_builder();
    assert(base_type_builder != nullptr);
    // 创建byte(位集)动态对象
    auto base_type = base_type_builder->build();
	// 创建int32构建器
    DynamicTypeBuilder_ptr base_type_builder2 =
        DynamicTypeBuilderFactory::get_instance()->create_int32_builder();
    assert(base_type_builder2 != nullptr);
    auto base_type2 = base_type_builder2->build(); // 创建int32动态对象
	// 创建string构建器
    DynamicTypeBuilder_ptr base_type_builder3 = 
        DynamicTypeBuilderFactory::get_instance()->create_string_builder();
    assert(base_type_builder3 != nullptr);
    auto base_type3 = base_type_builder3->build();
	
	// 创建结构体构建器
    DynamicTypeBuilder_ptr struct_type_builder =
        DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
    assert(struct_type_builder != nullptr);
	
    // 构建名为MyStruct的结构体
    struct_type_builder->set_name("MyStruct");
    // 增加结构体成员
    assert(struct_type_builder->add_member(0, "byte_value", base_type) ==
           ReturnCode_t::RETCODE_OK);
    assert(struct_type_builder->add_member(1, "int32_value", base_type2) ==
           ReturnCode_t::RETCODE_OK);

    assert(struct_type_builder->add_member(2, "string_value", base_type3) ==
           ReturnCode_t::RETCODE_OK);
	// 创建MyStruct动态类型对象
    auto struct_type = struct_type_builder->build();
    dynamic_struct_ptr_ = struct_type;
	// 创建类型支持对象
    eprosima::fastdds::dds::TypeSupport typeSupport(
        new eprosima::fastrtps::types::DynamicPubSubType(struct_type));

    typeSupport.get()->auto_fill_type_information(false);//指定是否自动填充类型信息
    typeSupport.get()->auto_fill_type_object(true);// 指定是否自动填充类型对象
    typeSupport.register_type(this->participant_);//注册类型
}

动态类型具体使用方法可以参考eprosima Fast DDS。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/717305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

namecheap 域名服务器 设置为Cloudflare

Namecheap 设置 自定义 域名服务器 登录Namecheap 帐户。进入后&#xff0c;将鼠标悬停在页面右上角的“帐户”选项上&#xff0c;然后选择“域列表”或选择左侧边栏中的“域列表” 参考 如何在 Cloudflare 帐户中域设置 DNS 记录

Simulink中Selector的使用

文章目录 0.prolog1 Starting and ending indices (port)2. Starting index (port)3. Starting index (dialog)4. Index vector (dialog)5. Index vector (port)Reference 0.prolog Index mode有两种&#xff0c;[one-based, zero-based]&#xff0c;分别是从1开始计数&#x…

波函数:描述量子世界的数学工具

亲爱的读者&#xff0c; 欢迎回到我们的量子力学系列文章。在前两篇文章中&#xff0c;我们介绍了量子力学的起源和基本概念。今天&#xff0c;我们将深入探讨量子力学的核心数学工具——波函数。 波函数是量子力学中的关键概念&#xff0c;它描述了一个量子系统的状态。波函…

Java转Go:java开发者转学go语言,请给我一些建议和学习推荐

在做开发时遇到最无理的需求就是部门没了&#x1f602; 目录 做开发时你遇到最无理的需求是什么&#xff1f;方向一&#xff1a;分享那些你遇到的无理需求方向二&#xff1a;面对这些无理需求时你是怎么做的&#xff1f;方向三&#xff1a;怎么避免遇见这些无理需求 java开发者…

赛效:怎么在线给Word文档加图片水印

1&#xff1a;在电脑网页上打开云组件&#xff0c;点击“Word转换”菜单里的“Word加水印&#xff08;图片&#xff09;”。 2&#xff1a;点击选择文件添加Word文档。 3&#xff1a;点击“选择水印图片”上传做水印的图片。 4&#xff1a;水印图片添加成功后可以选择水印角度&…

电商小程序开发指南:吸引并留住用户的秘诀

电商小程序作为微信生态内的新产品&#xff0c;有许多开发方面的内容需要学习&#xff0c;比如电商小程序的定位、功能、设计等。电商小程序是由商家开发并在微信平台上运行的小程序。它可以与微信公众号一起使用&#xff0c;也可以单独使用。 从传统电商到社交电商&#xff0…

24-正则表达式,应用场景

一、是什么 是一种用来匹配字符串的强有力的武器 它的设计思想是用一种描述性的语言定义一个规则&#xff0c;凡是符合规则的字符串&#xff0c;我们就认为它“匹配”了&#xff0c;否则&#xff0c;该字符串就是不合法的 在 JavaScript中&#xff0c;正则表达式也是对象&…

Spring Boot 缓存应用实践

缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。本文结合实际开发经验&#xff0c;从简单概念原理和代码入手&#xff0c;一步一步搭建一个简单的二级缓存系统。 一、通用缓存接口 1、缓存基础算法 FIFO&#xff08;First In Fir…

LVS负载均衡群集与LVS-NAT部署实战配置

文章目录 一.什么是集群1.群集的含义 二.集群使用在那个场景三.集群的分类1.负载均衡器群集2.高可用群集3.高性能运算群集 四.负载集群的架构1.第一层&#xff0c;负载调度器2.第二层&#xff0c;服务器池3.第三层&#xff0c;共享存储 五.负载均衡集群的工作模式1.地址转换 &a…

STM32中static和extern的用法

static&#xff1a; A. static变量 称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。 1. 静态局部变量 它与局部变量的区别在于: 在函数退出时, 这个变量始终存在, 但不能被其它 函数使用, 当再次进入该函数时, 将保存上次的结果。其它与局部变量一样。…

记一次自建靶场三层代理内网渗透过程

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 向日葵RCE外网突破02 Frp内网隧道搭建03 获取域内出网主机权限04 三层隧道搭建访问内网不出网主机 01 向日葵RCE外网突破 端口扫描探测存活端口&#xff0c;发现存在172.16.16.128:49773端口 访问…

【RPC】—Protobuf编码原理

Protobuf编码原理 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ Spring专栏&#x1f449;https://blog.csdn.net/weixin_53580595/category_12279588.html SpringMVC专…

【跨域认证】详解JWT,JWT是什么?

JSON Web Token&#xff08;缩写 JWT&#xff09;是目前最流行的跨域认证解决方案&#xff0c;本文介绍它的原理和用法。 一、跨域认证的问题 互联网服务离不开用户认证。一般流程是下面这样。 1、用户向服务器发送用户名和密码。 2、服务器验证通过后&#xff0c;在当前对话&…

[SSM]MyBatis使用javassist生成类和接口代理机制

目录 六、使用javassist生成类 6.1Javassist的使用 6.2使用Javassist生成DaoImpl类 七、MyBatis中接口代理机制及使用 7.1在之前的web应用中使用接口代理机制 7.2使用接口代理机制完成之前的CRUD(部分代码) 六、使用javassist生成类 6.1Javassist的使用 引入javassist依…

王道考研计算机网络第五章知识点汇总

5.1.1 传输层概述 复用&#xff1a;好比家里面每个人都要写信&#xff0c;向信箱里面投入信件&#xff0c;然后由邮递员取走。 分用&#xff1a;就是每个人都收到了各自的回信&#xff0c;然后从信箱中取走各自的信 5.2 UDP协议 注意&#xff1a;用户数据报和检验和都是指的整…

数学建模——插值(下)

本文是面向数学建模准备的&#xff0c;是介绍性文章&#xff0c;没有过多关于原理的说明&#xff01;&#xff01;&#xff01; 目录 一、2维插值原理及公式 1、二维插值问题 2、最邻近插值 3、分片线性插值 4、双线性插值 5、二维样条插值 二、二维插值及其Matlab工具箱…

记录一次Android侧滑需求代码

点击/滑动界面显示&#xff0c;不多说&#xff0c;上代码&#xff0c;性能未知 效果图 点击/滑动前界面 滑动后效果 布局 <?xml version"1.0" encoding"utf-8"?> <androidx.appcompat.widget.LinearLayoutCompat xmlns:android"…

【Cache】Squid代理服务器应用

文章目录 一、Squid 服务器的概念1. 代理服务器概述CDN 服务器 2. 代理的工作机制3. Squid 服务器的作用4. Squid 代理的类型 二、部署 Squid 服务器1. 安装 Squid 服务1.1 编译安装 Squid1.2 修改 Squid 的配置文件1.3 Squid 的运行控制1.4 创建 Squid 服务脚本1.5 supervisor…

在k8s集群中部署一个应用程序

一、 k8s集群简单介绍 上图描述的是拥有一个Master(主)节点和六个Worker(工作)节点的k8s集群 Master 负责管理集群 负责协调集群中的所有活动&#xff0c;例如调度应用程序&#xff0c;维护应用程序的状态&#xff0c;扩展和更新应用程序。 Worker节点(即图中的Node)是VM(虚…

模拟CSRF攻击

今天给大家表演一个拙劣的CSRF攻击。 我会编写两个应用&#xff1a;一个是正经应用&#xff0c;一个是钓鱼的应用。然后让后者攻击前者&#xff0c;让它打钱&#xff01; 一、绪论 1.1 先聊聊Cookie 参考&#xff1a;常用的本地存储——cookie篇 Cookie在八股文里面好像已…