Apollo 应用与源码分析:CyberRT-protobuf

2023-10-26

目录

概念

特点

优点

缺点

文件的创建

1.字段规则

2.数据类型

3.字段名称

4.字段编号

文件的编译

protobuf 编译命令编译

protobuf cmake 方式编译

使用bazel 编译

在protobuf 文件夹下创建build 文件

代码解释:

样例

protobuf

使用文件

代码解释:

BUILD 文件

编译执行

执行


概念

protobuf 全称 Protocol buffers,是 Google 研发的一种跨语言、跨平台的序列化数据结构的方式,是一个灵活的、高效的用于序列化数据的协议。

protobuf 在游戏领域比较常见,因为压缩比例大,那么数据的传输速度相对比较快。

bazel 中已经集成了protobuf的编译器。

特点

在序列化数据时常用的数据格式还有 XML、JSON等,相比较而言,protobuf 更小、效率更高且使用更为便捷,protobuf内置编译器,可以将protobuf 文件编译成 C++、Python、Java、C#、Go 等多种语言对应的代码,然后可以直接被对应语言使用,轻松实现对数据流的读或写操作而不需要再做特殊解析。

优点

  1. 高效 —— 序列化后字节占用空间比XML少3-10倍,序列化的时间效率比XML快20-100倍;
  2. 便捷 —— 可以将结构化数据封装为类,使用方便;
  3. 跨语言 —— 支持多种编程语言;
  4. 高兼容性 —— 当数据交互的双方使用同一数据协议,如果一方修改了数据结构,不影响另一方的使用。

缺点

  1. 二进制格式易读性差;
  2. 缺乏自描述。

文件的创建

// 使用的 proto 版本, Cyber RT 中目前使用的是 proto2
syntax = "proto2";
//包
package apollo.cyber.demo_base_proto;

//消息 --- message 是关键字,Student 消息名称
message Student {
    //字段
    //字段格式: 字段规则 数据类型 字段名称 字段编号
    required string name = 1;
    optional uint64 age = 2;
    optional double height = 3;
    repeated string books = 4;
}

proto 中的字段语法,字段就格式而言主要有四部分组成:字段规则数据类型字段名称字段编号,接下来分别介绍一下这四种格式。

1.字段规则

字段类型主要有如下三种:

  • required —— 调用时,必须提供该字段的值,否则该消息将被视为“未初始化”,不建议使用,当需要把字段修改为其他规则时,会存在兼容性问题。
  • optional —— 调用时该字段的值可以设置也可以不设置,不设置时,会根据数据类型生成默认值。
  • repeated —— 该规则字段可以以动态数组的方式存储多个数据。

2.数据类型

protobuf 中的数据类型与不同的编程语言存在一定的映射关系,具体可参考官方资料,如下:

除了上述基本的类型之外也有枚举和字典。

枚举:protobuf中的枚举类型使用方法与C++中的枚举类型类似,在将proto文件编译成C++代码后,其对应的类型也是C++中的枚举类型。

package pkgName;
// 定义枚举类型
enum DayName {
        Sun = 0;
        Mon = 1;
        Tues = 2;
        Wed = 3;
        Thur = 4;
        Fri = 5;
        Sat = 6;
}

message workDay {
                // 消息类型使用枚举类型
        optional DayName day = 1;
}

枚举常量的值必须在32位整数范围内,因为enum值是使用可编码方式存储的,对负数存储不够高效,因此不推荐在enum中使用负数。枚举类型可以定义在message内,也可以定义在message外,若定义在message内,其他message要使用则需要通过messageType.enumType来进行引用。默认情况下,枚举类型中的字段值不可重复,但是通过对enum添加**option allow_alias = true;**来达到对同一个枚举值起一个别名的目的,若不添加allow_alise并且有重复的枚举值编译的时候会报错。

package pkgName;
enum DayName {
                // 若不添加该option,会报错:
                // "pkgName.Test" uses the same enum value as "pkgName.Sat". If this is intended, set 'option allow_alias = true;' to the enum definition.
              option allow_alias = true;
        Sun = 0;
        Mon = 1;
        Tues = 2;
        Wed = 3;
        Thur = 4;
        Fri = 5;
        Sat = 6;
        Test = 6;    // Test与Sat字段值重名
}

map 数据类型:

需要注意:

(1) protobuf中的map实质上是unordered_map

(2) proto中map类型不能用optional/required/repeated任何类型修饰。

package pkgName;

message Tdata {
        map<int32,string> data = 1;
}

3.字段名称

字段名称就是变量名,其命名规则参考C++中的变量名命名规则即可。

4.字段编号

每个字段都有一个唯一编号,用于在消息的二进制格式中标识字段。

文件的编译

protobuf 编译命令编译

protoc ./xxxx.proto --cpp_out=.

上面是C++ 相关文件的编译方式,也有java和python的

protobuf cmake 方式编译

# 查找 protobuf
find_package(Protobuf REQUIRED)
if (PROTOBUF_FOUND)
    message("protobuf found")
else ()
    message(FATAL_ERROR "Cannot find Protobuf")
endif ()

# 编译 proto 为 .cpp 和 .h
set(PROTO_FILES proto/xxxx.proto) # 这里要写实际的proto 文件名称
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${PROTO_FILES})
message("PROTO_SRCS = ${PROTO_SRCS}")
message("PROTO_HDRS = ${PROTO_HDRS}")

# 关联 protobuf 到最后的二进制文件
add_executable(cmake_protobuf
        src/users.cpp
        src/main.cpp

        ${PROTO_SRCS}
        ${PROTO_HDRS})

target_include_directories(${PROJECT_NAME}
        PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
        PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
        PUBLIC ${PROTOBUF_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})

使用bazel 编译

在protobuf 文件夹下创建build 文件

load("//tools:python_rules.bzl", "py_proto_library")
package(default_visibility = ["//visibility:public"])
proto_library(
    name = "student_proto",
    srcs = ["student.proto"]
)

cc_proto_library(
    name = "student_cc",
    deps = [":student_proto"]
)

py_proto_library(
    name = "student_py",
    deps = [":student_proto"]
)

代码解释:

1.proto_library 函数

该函数用于生成 proto 文件对应的库,该库被其他编程语言创建依赖库时所依赖。

参数:

  • name 目标名称
  • srcs proto文件

2.cc_proto_library 函数

该函数用于生成C++相关的proto依赖库。

参数:

  • name 目标名称
  • deps 依赖的proto 库名称

3.py_proto_library 函数

该函数用于生成Python相关的proto依赖库。

参数:

  • name 目标名称
  • deps 依赖的proto 库名称

注意:

  1. 使用py_proto_library 必须声明 load("//tools:python_rules.bzl", "py_proto_library")。
  2. proto_library 函数的参数 name 值必须后缀 _proto 否则,python调用时会抛出异常。
  3. 为了方便后期使用,建议先添加语句:package(default_visibility = ["//visibility:public"])。

编译方式就是bazel build xxx/xxx/... ,然后就会在这个目录下生成对应的可以调用的中间文件。

样例

protobuf

// 使用的 proto 版本, Cyber RT 中目前使用的是 proto2
syntax = "proto2";
//包
package apollo.cyber.demo_base_proto;

//消息 --- message 是关键字,Student 消息名称
message Student {
    //字段
    //字段格式: 字段规则 数据类型 字段名称 字段编号
    required string name = 1;
    optional uint64 age = 2;
    optional double height = 3;
    repeated string books = 4;
}

使用文件

/*  
    演示 C++中 protobuf 的基本读写使用
*/
#include "cyber/demo_base_proto/student.pb.h"

int main(int argc, char const *argv[])
{
    //创建对象
    apollo::cyber::demo_base_proto::Student stu;
    //数据写
    stu.set_name("zhangsan");
    stu.set_age(18);
    stu.set_height(1.75);
    stu.add_books("yuwen");
    stu.add_books("c++");
    stu.add_books("Python");

    //数据读
    std::string name = stu.name();
    uint64_t age = stu.age();
    double height = stu.height();
    std::cout << name << " == " << age << " == " << height << " == "; 
    for (int i = 0; i < stu.books_size(); i++)
    {
        std::cout << stu.books(i) << "-";
    }
    std::cout << std::endl;

    return 0;
}

代码解释:

proto 文件生成的对应的 C++ 源码中,字段的设置与获取有其默认规则:

  1. 如果是非 repeated 规则的字段:那么字段值的设置函数对应的格式为:set_xxx(value),获取函数对应的格式为xxx()。
  2. 如果是 repeated 规则的字段:那么字段值的设置函数对应的格式为:add_xxx(),获取函数对应的格式为xxx(索引),另外还可以通过函数 xxx_size() 获取数组中元素的个数。

其中 xxx 为字段名称。

BUILD 文件

cc_binary(
    name = "test_student",
    srcs = ["test_student.cc"],
    deps = [":student_cc"],
)

编译执行

bazel build cyber/<user dir>/...

执行

./bazel-bin/cyber/<user dir>/test_student

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apollo 应用与源码分析:CyberRT-protobuf 的相关文章

  • C# 中的随机数 [重复]

    这个问题在这里已经有答案了 可能的重复 随机数生成器没有按我计划的方式工作 C https stackoverflow com questions 767999 random number generator not working the
  • 前摄器和异步写入

    升压asio http www boost org doc libs 1 46 1 doc html boost asio html实现基于前摄器设计模式ACE前摄器 http www cse wustl edu schmidt PDF p
  • C# 中的可选数组参数[重复]

    这个问题在这里已经有答案了 可能的重复 在 C 中传递一个空数组作为可选参数的默认值 https stackoverflow com questions 3480382 passing an empty array as default v
  • 无与伦比的括号宏怪异

    根据 C99 规则预处理以下 3 行的正确输出是什么 define y x x define x a y a x 1 x 2 顺便说一句 linux 下的 cpp 会产生错误消息 但我不明白为什么答案不简单 1 2 假设 cpp 是正确的而
  • 单击旁边的按钮时如何引用动态创建的标签 [Qt]

    每次按下 添加客户端 按钮时 减号按钮 客户端名称 客户端计数器和加号按钮都会以水平线添加到网格布局中 我想在按下加号 减号按钮时更新计数 QLabel 这是我的代码 include widget h include ui widget h
  • WPF 将“菜单”键称为什么?

    我正在查看此处定义的键 http msdn microsoft com en us library system windows input key aspx http msdn microsoft com en us library sy
  • C++ 模板特化/重载

    首先 我对这个问题的模糊标题感到抱歉 我不知道如何总结它 我想要实现的目标如下 我希望能够将不同类型的模板非类型参数传递给同一个类模板 从而产生不同的实例化 像这样的事情 Foo lt 1 gt Foo lt 1 gt different
  • 绑定到 DataContext 的 WPF 样式 DataTrigger 不起作用

    我有一个 TextBox 其样式具有可更改文本的 DataTrigger 如下所示
  • Windows 7 跳转列表(Windows 窗体、C#)

    有谁知道如何在 C 中自定义与我自己的应用程序相关的 Windows 跳转列表功能 我知道可以做到 但我在 MSDN 上找不到任何与 C Windows7 相关的内容 到目前为止 我能找到的与 W7 和 C 相关的唯一信息只是我已经阅读过的
  • 二维数组,在 C 中使用 calloc

    我正在尝试创建一个二维字符数组来存储字符行 例如 lines 0 Hello lines 1 Your Back lines 2 Bye 由于行必须是动态的 因为我一开始不知道需要多少行 这是我的代码 int i char lines ch
  • 限制在指定时间访问互联网

    我正在尝试做一个家长控制软件项目 我阻止了特定网站并使用主机文件取消阻止它们 后来 我尝试通过以编程方式禁用和启用 LAN 连接来禁用 启用互联网访问 C 有没有办法在特定时间阻止互联网访问 例如8 January 2013之间20 00
  • Mono WebClient 编码问题

    我正在尝试移植 NET应用程序从 Windows 到 Mono 但某些在 Windows 上运行的代码不再运行 正如预期的那样 on mono WebClient client new WebClient Console WriteLine
  • C# 泛型 - 可以创建具有 n 个泛型类型的方法..?

    我认为这是不可能的 但这里 我想添加可以处理 n 个泛型的方法 例如 bool
  • CUDA 估计 2D 网格数据的每块线程数和块数

    首先我要说的是 我已经仔细阅读了所有类似的问题 确定每个块的线程和每个网格的块 https stackoverflow com questions 4391162 cuda determining threads per block blo
  • 用于嵌入式服务器的 Web 技术

    我最近开始了一个针对嵌入式设备的新 Web 开发项目 并希望征求一些有关使用技术的建议 该设备将提供 HTML 页面 其中包括用于从 JSON 服务器检索数据的 AJAX 代码 我们暂时使用 Cherokee 作为 Web 服务器 但我们并
  • ofstream 不适用于 Windows 7 隐藏文件

    我意识到ofstream不适用于 Windows 7 隐藏文件 这是快速测试代码 include
  • CRC 16 -DECT 与聚 x^16 + x^10 + x^8 + x^7 + x^3 + 1

    相信我 我已经尝试过编写这个代码 尝试过谷歌 但没有任何运气 我正在尝试使用这个 Poly 实现 CRC16 x 16 x 10 x 8 x 7 x 3 1 使用C语言 因为我对 PHP 有了更好的了解 所以我试图让一个函数运行 但我没有得
  • 日期时间类型转换器

    我有下面的代码将字符串转换为 T 类型 它适用于所有其他类型 但当 T 为 DateTime 类型时会出现错误 TypeConverter c TypeDescriptor GetConverter typeof T return T c
  • 图像调整大小性能:System.Drawing 与 System.Windows.Media

    我遇到了需要调整大量图像大小的情况 这些图像目前在文件系统上存储为 jpg 文件 但我希望稍后在项目中内存中只有 byte 源图像大小是可变的 但输出应该是 3 个不同的预定大小 应保留长宽比 用空白填充原始图像 即 将调整非常高的图像大小
  • 根据具体数据计算锯齿波和三角波

    我需要计算三角形和锯齿波 但由于我的模型和我能够使用的数据 它有点复杂 但也许我只是感到困惑 我能够计算我的正弦波 但我并没有真正使用帧计数器 我所做的是 计算theta increment下次需要计算样本时可以使用的变量 这工作起来是这样

随机推荐

  • 为什么会有ETH和ETC?the DAO攻击事件2周年祭

    前两天 跟一位HiBlock区块链社区的用户私聊 他问我一个问题 同样是智能合约 为什么会有以太坊和以太经典 又为什么会有相应的ETH和ETC 两者价格还相差如此之大 转给他一篇the DAO事件的文章后突然发现 the DAO攻击事件已经
  • Spring AOP 应用场景之--日志收集(含代码)

    在学习了 Spring AOP 知识之后 只了解了其一些基本的概念 比如它是为了解决 OOP 的弊端 使代码更易于维护 使用了动态代理 Spring 中有两种动态代理实现方式 一种是 JDK 一种是Cglib 使用场景有权限 缓存 日志 b
  • linux命令大全 which

    参考 Linux命令大全 程序员工具箱 1 命令 which 从 PATH 路径下查找某个命令的全路径 2 使用样例 查看 java 命令的全路径 which java 3 使用方法 which programnam
  • 基于JdbcTemplate的一种通用数据库操作帮助工具

    工具介绍 基于JdbcTemplate的通用操作数据库的帮助工具 借助阿里巴巴的开源工具fastjson实现实体的转json字符串以及params的解析 用法 1 建立与数据库表相对应的entity对象 package cn flyzy20
  • APB协议UVM验证环境的搭建

    APB协议UVM验证环境的搭建 一 编译文件 只需编译这两个文件即可 apb pkg sv 里面包含了 apb svh 即编译apb pkg sv这个文件的同时 也会编译所需要的所有的头文件 ifndef APB PKG SV define
  • 绕过专题

    绕过验证码专题 原理 直接截取返回包的cookie或者json流中的验证码进行绕过 提取出验证码进行直接验证即可 gt 绕过 方法 利用burp中的Extractor或者是Bp自带的Marco进行自动化测试 典型类型 如返回包的cookie
  • Java生成一个包含所有数字大小写字母的集合

    利用循环给集合添加所有数字和字母 import java util ArrayList ArrayList
  • steam移动所有文件至新库文件夹失败_不想次次重复下载游戏?手把手教你打造移动游戏、软件库...

    大家好 我是黄昏百分百 之前我有幸获邀参与了七彩虹RTX 3080显卡的媒体首测 在测试过程中 我购买了很多的3A大作 下着下着游戏 就发现固态硬盘不够用了 所以 我觉得升级我的固态硬盘 于是 就有了今天这篇如何通过固态硬盘打造移动游戏 软
  • 【Android自动化测试】5个必备的测试框架

    Appium Appium是一个开源的移动测试工具 支持iOS和Android 它可以用来测试任何类型的移动应用 原生 网络和混合 作为一个跨平台的工具 你可以在不同的平台上运行相同的测试 为了实现跨平台的功能 Appium使用了供应商提供
  • C++析构函数调用异常问题研究

    最近又遇到一个奇葩问题 程序在自己的开发机器和某些机器上运行完好 但是在测试人员的几台机器上运行就直接推出了 开始以为是出现了野指针 因为delete野指针时程序会直接退出 代码翻来覆去过来即便确认没有野指针后问题就陷入了死循环 经过多次调
  • mysql超时连接问题

    一 问题 nested exception is com mysql jdbc exceptions jdbc4 CommunicationsException Communications link failure The last pa
  • 28岁,从字节退休了···

    大厂一直是每个程序员都向往职业目标 大厂意味着薪资高 福利好 倍有面儿 而且发展空间也大 甚至有人调侃不想进大厂的程序员不是好程序员 而在网上 也有各个网友分享自己在大厂的经历 在某平台还有一个近2600万浏览的话题 在字节跳动工作是怎么样
  • jvm堆大小的设置

    问题引入 Xmx10240m Xms10240m Xmn5120m XXSurvivorRatio 3 其最小内存值和Survivor区总大小分别是 10240m 2048m 解析 Xmx 最大堆大小 Xms 初始堆大小 Xmn 年轻代大小
  • es6常见的相关问题

    文章目录 ES6常见的相关问题 1 var let const之间的区别 1 var 注意点1 变量提升 注意点2 块级作用域 注意点3 重复声明 2 let ES6 注意点1 变量提升 不存在 注意点2 块级作用域 注意点3 重复声明 注
  • ICCV2019 oral papers

    ICCV2019 oral papers Exploring Randomly Wired Neural Networks for Image Recognition Paper Video Progressive Differentiab
  • 10个良心网站推荐

    对效率工具感兴趣的可以看一看我的往期视频 10个良心网站推荐第三期 10个良心网站推荐 10个良心网站推荐第二期 av76255938 13个逆天网站工具 av70359966 10个改变生活的网站 10个改变生活的网站 本期推荐 1 Vi
  • ctf从零开始学0x02 ctf的逆向reverse 常见思路和如何入门(文末)

    逆向是啥 很多人一开始都感到很糊涂 下面给出相关的概念 对于相关如何打逆向的基础可以看 https blog csdn net qq 43504939 article details 90246409 其中 80 的题目都与crypto结合
  • 005-1基于深度优先搜索查找图中连通路径

    基于图的深度优先搜索 图学习笔记索引 本文参考 算法 第4版 基于图的深度优先搜索 1 自定义输入流In 2 定义背包类Bag 3 无向图G的构造 4 深度优先搜索DepthFirstSearch 5 使用深度优先搜索查找连通路径Depth
  • Win7 X86上搭建Android开发环境

    Android SDK有Mac Linux和Windows三个平台的版本 处于个人习惯 决定在Win7 X86的电脑上搭建Android开发环境 windows平台搭建Android开发环境 需要以下相关安装包 1 JDK6 需下载并安装
  • Apollo 应用与源码分析:CyberRT-protobuf

    目录 概念 特点 优点 缺点 文件的创建 1 字段规则 2 数据类型 3 字段名称 4 字段编号 文件的编译 protobuf 编译命令编译 protobuf cmake 方式编译 使用bazel 编译 在protobuf 文件夹下创建bu