protocbuf c++示例
Protocol Buffers(简称Protobuf)是由Google开发的一种语言中立、平台中立、可扩展的序列化数据格式,可以用于数据存储或RPC(远程过程调用)系统间的数据交换。它类似于XML或JSON,但更小、更快、更简单。
Protobuf的主要特点包括:
- 高效:
空间效率:Protobuf使用二进制格式存储数据,比XML和JSON更节省空间。
时间效率:解析和序列化速度更快,适合高性能应用。 - 语言中立:
支持多种编程语言,包括C++、Java、Python、Go、Ruby、JavaScript、C#等,便于跨语言、跨平台的数据交换。 - 自动代码生成:
通过.proto文件定义数据结构后,Protobuf编译器(protoc)可以自动生成相应语言的源代码,包括数据访问类和方法。 - 向后兼容性:
支持数据的向前和向后兼容性,可以在不破坏现有系统的情况下添加或删除字段。 - 扩展性强:
-可以方便地添加新的数据类型和字段,而不会破坏已经存在的系统。 - 平台无关:
可以在不同平台上使用,无论是服务器、客户端还是嵌入式系统。
1.关键字
- required:必须在序列化后的消息中设置该字段的值,如果未设置,则该消息不能被序列化(protoc3时已被删除使用)。
- optional:表示该字段为可选字段,可以有值也可以没有值(默认值为定义字段时指定的默认值,如果没有指定默认值,则为特定类型的默认值,例如对于数字类型是0,对于字符串类型是空字符串)。
- repeated:表示该字段可以包含0个或多个元素,类似于C++中的std::vector。
- map:这是一个配对键/值字段类型。
2.保留字段
2.1 前置条件
- 如果操作不当,删除字段可能会导致严重问题。
- 当不再需要某个字段且已从客户端代码中删除所有引用时,可以从消息中删除该字段定义。但是,必须- 保留已删除的字段号。如果不保留字段号,开发人员将来有可能重新使用该字段号。
- 还应保留字段名称,以允许消息的 JSON 和 TextFormat 编码继续进行解析。
2.2 执行方案
-
如果通过完全删除字段或将其注释掉来更新消息类型,则未来的开发人员可以在对类型进行自己的更新时重新使用该字段号。重复使用字段编号会使解码线格式消息变得模棱两可。
protobuf 线格式精简,无法检测使用一种定义编码并使用另一种定义解码的字段。 -
为确保这种情况不会发生,请将已删除的字段号添加到 reserved 列表中。为确保消息的 JSON 和 TextFormat 实例仍可解析,还应将已删除的字段名称添加到 reserved 列表中。
-
如果任何未来的开发人员尝试使用这些保留的字段号或名称,则协议缓冲区编译器会发出警告。
2.3 使用示例
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
2.4 注意事项
- 保留的字段号范围是包含的(9 到 11 与 9、10、11 相同)。请注意,不能在同一个 reserved 语句中混合字段名称和字段号。
3. 枚举
3.1 有别于C++的一点
- 各字段之间统一使用分号(;)隔开,第一个字段对应的常量值必须是零。
3.2 使用不同的枚举常量表示相同的值之前,需要更改配置
- 需要将option 中的 allow_alias 设置为true;
3.3 相关事项
- 枚举常量必须在32位整数的范围内。
- 负值效率低下,不推荐使用。
- 可以在消息定义中定义 enum,也可以在外部定义,外部定义的这些enum可以重复用于 .proto 文件中的任何消息定义。
- 可以使用在一个消息中声明的enum类型作为另一个消息(message)中字段的类型,使用语法 MessageType.EnumType。
3.4 注意删除时保留字段的问题,同message
3.5 使用示例
enum Sex{
option allow_alias = ture;//允许使用多个常量表示相同的值
MAN = 0;
MEN = 0;
MOMAN = 1;
WOMEN = 1;
}
4. 命名空间
4.1 使用关键字package设置命名空间
4.2 使用示例
package PersonalMessage;//生成的c++代码将处于命名空间PersonalMessage中
5. 导入定义import
类似于#include的功能。
6. 编译指令
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/Person.proto
-
-I=$SRC_DIR:指定.proto文件所在位置,不指定则默认当前位置;
-
–cpp_out=$DST_DIR:指定生成源码放置的位置;
-
$SRC_DIR/Person.proto:指定要操作的.proto文件
-
person.pb.h:声明生成的类的头文件
-
person.pb.cc:包含生成类的实现
7. protoc使用示例
7.1 .proto文件
- Person.proto文件演示了如何使用protoc生成c++代码,编译指令:
protoc --cpp_out=. ./Person.proto
- 编译成功会在当前目录生成person.pb.h和person.pb.cc
syntax = "proto3";
package PersonalMessage;
enum Sex{
option allow_alias = true;//允许使用多个常量表示相同的值
MAN = 0;
MEN = 0;
MOMAN = 1;
WOMEN = 1;
}
message Person{
optional string name = 1;//姓名