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

news2024/9/25 3:26:59

目录

概念

特点

优点

缺点

文件的创建

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

 

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

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

相关文章

Python:入门与基本语法

目录 一、Python环境 官方下载 Python开发工具 插件安装 二、基本数据类型 动态语言的体现 静态语言的体现 弱语言的体现 强语言的体现 三、基本数据类型 java八大基本数据类型 Python四大基本数据类型 案例 基本数据类型 test01 源码 引用数据类型 列表 test02 源码…

你不知道的SQL语言数据库原理

1、SQL的概述 SQL全称&#xff1a; Structured Query Language&#xff0c;是结构化查询语言&#xff0c;用于访问和处理数据库的标准的计算机语言。 SQL语言1974年由Boyce和Chamberlin提出&#xff0c;并首先在IBM公司研制的关系数据库系统SystemR上实现。 美国国家标准局(AN…

【配电网重构】负荷平衡的配电网重构【含Matlab源码 2180期】

⛄一、 负荷平衡的配电网重构 1 引言 配电网网络重构是指在正常或非正常运行条件下通过改变开关的开关状态来改变网络的拓扑结构。配电网故障恢复供电是指配电网发生故障后,在故障已被定位和隔离的基础上,研究如何恢复对无故障停电区域供电的问题,本文简称为故障恢复。故障恢复…

Spring Cloud Alibaba 整合 Nacos

写在最前 项目 GitHub 地址 mingyue-springcloud-learning 【mingyue-springcloud-user、mingyue-springcloud-member】 阅读推荐 Spring Cloud 入门必读Spring Cloud Alibaba 入门必读 版本声明 spring-boot: 2.7.5 spring-cloud: 2021.0.5 spring-cloud-alibaba: 2021.0.4…

论文阅读 Fast Reinforcement Learning Via Slow Reinforcement Learning

论文阅读 RL^2 Fast Reinforcement Learning Via Slow Reinforcement Learning1. 摘要2.introduction3. 实现4.小结1. 摘要 强化学习可以对于单个任务有较好的效果&#xff0c;但需要大量的尝试。动物往往可以通过少量的尝试就获得很好的效果。原因在于动物可以更好地使用先验…

学习笔记——Java Stream 源码学习

思路 先上一段代码 List<User> userList new ArrayList<>();for (int i 0; i < 10; i) {userList.add(new User(i, "wtq", "1234"));}userList.stream().filter(user -> user.getUserId() > 3).filter(user -> user.getUserId(…

【JVM】字节码技术:图解字节码形式下的 方法执行流程

一、源文件 package cn.itcast.jvm.t3.bytecode;/** * 演示 字节码指令 和 操作数栈、常量池的关系 */ public class Demo3_1 {public static void main(String[] args) {int a 10;int b Short.MAX_VALUE 1;int c a b;System.out.println(c);} }二、反编译的字节码文件 …

《Go语言精进之路,从新手到高手的编程思想、方法和技巧1》读书笔记和分享

Go语言精进之路&#xff0c;从新手到高手的编程思想、方法和技巧读书分享1 本书定位2 本书内容总览3 选择本书的原因4 小收获分享第7-12条 真的不知道咋命名第13-19条 能用——怎么用更好5 个人总结第一部分 熟知 Go 语言的一切第 1 条 了解 Go 语言的诞生与演进第 2 条 选择适…

甘露糖-聚乙二醇-CY5.5 /Cy5.5-PEG-mannose

甘露糖-聚乙二醇-CY5.5 /Cy5.5-PEG-mannose 中文名称&#xff1a;甘露糖-近红外染料CY5.5 英文名称&#xff1a;mannose-Cyanine5.5 别称&#xff1a;CY5.5修饰甘露糖&#xff0c;CY5.5-甘露糖 PEG分子量可选&#xff1a;350、550、750、1k、2k、34k、5k 包装&#xff1a;…

es(网站的搜索技术)

一。搜索技术 springboot集成es ElasticsearchRestTemplate mapping 继承 extends ElasticsearchRepository 实体类写的映射关系&#xff1a; 注解&#xff1a;Document用来声明Java对象与ElasticSearch索引的关系 indexName 索引名称(是字母的话必须是小…

线性回归的神经网络法——机器学习

一、算法思想 线性回归方程在神经网络深度学习中线性回归方程是需要掌握的最基础的式子&#xff0c;就是&#xff1a;ywxb,其中w,b是未知的。 神经网络就是可以通过收集大量的数据集&#xff0c;然后将这些数据集进行训练后得到几个较为准确的参数&#xff0c;训练数据集后会得…

MongoDB单机集群方案及详解

目录帮助文档MongoDB在企业级网站中的定位单机MongoDB部署集群&#xff08;副本集&#xff09;集群&#xff08;副本集仲裁&#xff09;集群&#xff08;分片&#xff09;mongo运行原理mongo管理小工具推荐帮助文档 MongoDB官方更新速度过快&#xff0c;语法不断更新&#xff…

云南民族文化旅游网页设计制作 简单静态HTML网页作品 我的家乡网页作业成品 学生旅游网站模板

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

m基于光纤光栅传感网接入GPON的光纤通信系统matlab性能仿真,包括解码,解封装,分接,码率恢复,解帧,拆包,译码

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 接入处理系统模块化设计&#xff1a; 传感器接收到的信息转换为二进制信息&#xff08;这个我们可以直接模拟出随机的二进制序列来表示传感器的数据&#xff0c;首先设置一组数据&#…

maven学习: 使用Maven构建Web项目

5.1 Maven中Web项目的结构 ​ 在java的世界中&#xff0c;Web应用占有很大的地位&#xff0c;而它的标准打包方式是WAR。WAR与JAR类似&#xff0c;但它包含了更多内容&#xff0c;如JSP文件、Servlet、web.xml配置文件、静态web资源&#xff08;如html&#xff0c;css&#xf…

Python Gui之tkinter

GUI是什么 目录 1。GUI编程的核心步骤和第一个GUI程序 2.tkinter主窗口​​​​​​​ 3.GUI的整体描述 常用组件汇总 4.简单的组件 1.Label标签 2.Options选项详解 3.Button 4.Entry单行文本框 5.Text多行文本框 1。GUI编程的核心步骤和第一个GUI程序 from tkinte…

biaffine model:Named Entity Recognition as Dependency Parsing

论文名称&#xff1a;Named Entity Recognition as Dependency Parsing 论文地址&#xff1a;https://www.aclweb.org/anthology/2020.acl-main.577/ 前提说明 本文主要参考了以下资料 nlp_paper_study_information_extraction/code_pytorch.md at main km1994/nlp_paper_s…

ASEMI肖特基二极管SBT40100VFCT规格,SBT40100VFCT封装

编辑-Z ASEMI肖特基二极管SBT40100VFCT参数&#xff1a; 型号&#xff1a;SBT40100VFCT 最大重复峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;100V 最大平均正向整流输出电流&#xff08;IF&#xff09;&#xff1a;40A 峰值正向浪涌电流&#xff08;IFSM&#…

使用kubeadm搭建高可用集群-k8s相关组件及1.16版本的安装部署

本文是向大家分享k8s相关组件及1.16版本的安装部署&#xff0c;它能够让大家初步了解k8s核心组件的原理及k8s的相关优势&#xff0c;有兴趣的同学可以部署安装下。 什么是kubernetes kubernetes是Google 开源的容器集群管理系统&#xff0c;是大规模容器应用编排系统&#xff…

ubuntu下jupyter notebook设置远程访问

1. 安装anaconda 推荐安装anaconda&#xff0c;安装后就会包含jupyter notebook 使用命令conda list或者pip list查看jupyter notebook包&#xff0c;这里不多介绍 2. 生成默认配置文件 在ubuntu环境下&#xff0c;安装jupyter notebook后&#xff0c;用户主目录中会有一个…