序言
apollo采用google开源的 protocol buffer协议用于数据的序列化和反序列化。配置文件作为序列化和反序列化的一个应用广泛存在于apollo项目中,因此,掌握pb协议的使用后续对源码实现功能拓展。
一、项目对Protobuf的依赖
protobuf对项目来说相当于第三方库。bazel对于第三方库的处理方式可见下图:
protobuf和bazel都是谷歌的,因此在WORKSPACE中下载bazel提供的rules_proto规则即可。rules_proto中已经封装好了相关的proto依赖函数,在workspace调用该函数即可。具体步骤如下:
进入github界面找到rule_cc目录,打开目录下的WORKSPACE。将代码里的下属内容复制到自己项目的WORKSPACE中
#从远程仓库中下载rules_proto规则代码库
http_archive(
name = "rules_proto",
sha256 = "9a0503631679e9ab4e27d891ea60fee3e86a85654ea2048cae25516171dd260e",
strip_prefix = "rules_proto-e51f588e5932966ab9e63e0b0f6de6f740cf04c4",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/e51f588e5932966ab9e63e0b0f6de6f740cf04c4.tar.gz",
"https://github.com/bazelbuild/rules_proto/archive/e51f588e5932966ab9e63e0b0f6de6f740cf04c4.tar.gz",
],
)
#加载rules_proto规则
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
#加载rules_proto的中依赖
rules_proto_dependencies()
#加载rules_proto中的工具链
rules_proto_toolchains()
至此,就可以就完成了项目对protobuf库的依赖了。
二、序列化与反序列化
1.what and why?
序列化:把对象转化为可传输的字节序列过程称为序列化。
反序列化:把字节序列还原为对象的过程称为反序列化。
为什么需要序列化和反序列化?系统底层中的数据的传输形式是简单的字节序列形式传递,不认识高级语言封装成的对象。序列化是为了把进程中的对象转化为易于跨平台存储和网络传输的字节数据,反序列化就是把存储过来的或网络传输过来的数据解析为进程中对象。对象转换为字节数据和字节数据解析为对象都需要协议,Google提出了protobuf协议。
apollo中主要是将protobuf用于CyberRT的不同主机间通信时的序列化和反序列化,以及用为模块配置文件。本文主要分析protobuf作为配置文件的用途。
2. 优缺点:
优点:效率高,跨平台多语言,拓展性和兼容好,使用简单参考此文章。
效率高:采用L(length)-V(value)-T(Tage),方式编码,不需要", {, }, :等分隔符来结构化信息,因此序列化之后的体积小,同时序列化速度和反序列化速度比XML和Json块。
支持多语言:有些行业时多语言开发的,如自动驾驶。C++主要处理计算任务,而python用于提供接口,因此protobuf很适用,不会出现语言障碍。
缺点:不具备自描述能力,数据可读性差。
三、protobuf实现原理
对于Protobuf采用的编码原理主要参考文章1 ,文章2。protobuf基本框架如下图:
四、.probotbuf文件基本概念
1. 消息的组成
syntax = "proto2" ///proto使用的语法是”proto2“
///将来编译为C++的类之后,
///该类所处的命名空间为apollo::Myth::general
package apollo.Myth.general
///消息
///消息是由消息类型 + 字段组成
///消息类型:message StatusPb
///字段1:optional ErrorCode error_code = 1 [default = OK];
///字段2:optional string msg = 2;
///字段的组成:修饰符 数据类型 标识符 编号 (默认值)
message StatusPb {
optional ErrorCode error_code = 1 [default = OK];
optional string msg = 2;
}
2.修饰符
3.编号
4. C++ API