Protocol Buffer使用指南之C++实例

我们知道Protocol Buffer有一个重要的特性——跨语言,它支持C++,Python,Java等多种语言。本文围绕着C++语言实例来往下展开,主要介绍以下几点:如何在.proto文件中定义message类型,如何使用protoc编译器,如何使用Protobuf提供的C++ API去读/写数据。
1.为什么使用Protocol Buffers?

首先,假设有如下场景:一个“通讯录”应用程序,需要去从一个文件中读取或写入每个人的相关信息,这些信息主要包括每个人的ID,姓名,邮箱以及电话号码等。那么,你将采用何种方法来序列化或反序列化这些结构化的数据呢?

这里,我们先给出如下几种方案:

(1)以二进制形式去读/写加载到内存中的结构化数据。但是,该方法要求读/写双方具有相同的内存布局以及字节顺序。比如,您必须考虑到字节对齐的方式(一般将其设为1字节对齐)、字节顺序的大小端转换等问题。其次,这种方式还会给这种结构化的数据带来了难以扩展的弊端。

(2)您可以自定义一种特殊的方式来将数据编码为单个字符串。虽然这是一种简单灵活的方法,适用于编码简单的数据。但是,在编码和解析的过程会增加运行时成本。

(3)使用XML。将数据序列化为可读的XML格式,这对于那些想要将自己的数据与其他应用程序共享的场景来说是一个不错的选择。然而,XML却是相当的消耗空间的,编码/解码的过程会给应用程序带来巨大的性能损失。

针对于上面提到的种种弊端,Google的Protocol Buffer横空出世,给出了解决方案(嗯,故事总是这样发展的…)。

通过Protocol Buffer,您可以编写一个.proto文件来描述您希望存储的数据结构。在此基础上,Protocol Buffer会给您创建一个相应的类(该类会为您提供各种操作您所定义的数据结构的接口),以高效的二进制格式实现数据的自动编码和解析。更为重要的一点是,Protocol Buffer支持后期更新扩展。

2.编写.proto文件

接着上面假设的场景,我们来定义一个“通讯录”的.proto文件,以addressbook.proto命名。此场景下:

(1)首先,为通讯录中的每一个“人”定义为一个message数据结构(命名Person),相应地,每个人都应该包含字段:姓名,id,邮件以及电话号码等。

(2)其次,每个人可能有多个电话号码,可能是手机、家庭座机或办公座机。所以,我们将电话号码字段定义为嵌套在Person结构中的另一个message数据结构(命名PhoneNumber);

(3)最后,电话号码的类型定义为一个枚举型(命名PhoneType)。

于是,我们得到:

其中的语法细节此处不再赘述,可参考前一篇博文(Protocol Buffer语法规范:http://dulishu.top/protocol-buffer-syntax/)。

3.编译.proto文件

现在我们已经写好了addressbook.proto文件了,离能够读/写AddressBook结构化数据还差一步:使用protoc编译.proto文件,生成我们所需要的C++类文件。

protoc命令的使用方法在前一篇博文中也有所介绍,比如,此处我们输入如下命令:

如上所示,该目录下多了两个文件:addressbook.pb.h为生成类的头文件, addressbook.pb.cc为该类的具体实现。

4.Protobuf API

如上所示,使用protoc命令生成了addressbook类,该类包含了我们序列化/反序列化需要用到的所有方法,幸运的是,这些方法已经全部由Protobuf帮我们实现了。在使用之前,我们还是有必要了解一些常用的API。

(1)字段相关API

Protobuf会为在addressbook.proto文件中声明的每一个message类型生成一个同名的类,就Person类而言,Protoc编译器为Person中的每一个字段都生成了相应的操纵接口。比如,对name, id, eamil以及phones而言有:

如上所示,我为每个字段的API都添加了相应的注释,此处不再赘述。需要说明的是,对不同的字段而言,protobuf生成的操纵接口会稍有差异,详情请见参考链接[2]。

(2)message相关API

除了上述提及的字段相关API,protobuf还为message类型生成了相关API,用来检查或操作整个message,比如:

(3)序列化/反序列化相关API

对每个Protobuf类而言,protobuf同样提供了使用二进制形式读/写这些消息的接口,主要有:

5.实例

下面两个实例使用Protobuf提供的C++ API,分别向“通讯录”addressbook.txt文件中写入和读取每个人的相关信息。

(1)write.cpp

编译、运行,并添加一条记录:

(2)read.cpp

编译、运行:

6.其他

OK, Protocol Buffer初阶内容就介绍到这里,与君共享。其他未述高阶内容等以后用到再做总结吧~

 

参考:
[1]. https://developers.google.com/protocol-buffers/docs/cpptutorial
[2]. https://developers.google.com/protocol-buffers/docs/reference/cpp-generated
[3]. https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message.html#Message

发表评论

电子邮件地址不会被公开。 必填项已用*标注