文章目录
1,下载安装包
https://github.com/protocolbuffers/protobuf/releases/latest
For example: if you only need C++, download `protobuf-cpp-[VERSION].tar.gz`; if
you need C++ and Java, download `protobuf-java-[VERSION].tar.gz` (every package
contains C++ source already); if you need C++ and multiple other languages,
download `protobuf-all-[VERSION].tar.gz`.
2,解压安装
$ tar -vxf protobuf-cpp-3.8.0.tar.gz
$ cd protobuf-3.8.0/
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig # refresh shared library cache.
2.1,查看版本
$ protoc --version
3,使用
https://www.jianshu.com/p/419efe983cb2
枚举类为什么有0
https://blog.csdn.net/skh2015java/article/details/78404235
https://blog.csdn.net/hry2015/article/details/70766603
https://www.cnblogs.com/zhouyang209117/p/7218719.html
https://blog.csdn.net/yang332233/article/details/83657735
3.1,定义数据结构体---编写config.proto
// 指定版本号为proto3; 否则默认使用proto2
// 注意:版本号指定必须放在第一行
syntax = "proto3";
// 包名,用来防止Protocol Buffers name space里的名字冲突
package config;
// 引入外部的proto对象
import "google/protobuf/any.proto";
// 生成java文件后的包名
option java_package = "com.hry.spring.proto.complex";
option java_outer_classname = "MyComplexObjectEntity";
message ComplexObject {
// Message里每个成员变量都有一个唯一的数字标志( Assigning Tags)
int32 id = 1;// singular, 默认值,表示成员只有0个或者1个
string name = 2;//
string email = 3;//
repeated string sons = 4; // repeated 列表
Gender gender = 5; // Enum值
repeated Result result = 6; // 新的对象List
repeated google.protobuf.Any any = 7; // Any对象
map<string, MapVaule> map = 8; // 定义Map对象
// reserved
reserved 12, 15, 9 to 11; // 预留将来使用的Assigning Tags,
reserved "foo", "bar"; // 预留将来使用的filed name
}
enum Gender {
// option allow_alias = true;
MAN = 0;
WOMAN = 1;
}
// 定义一个新的对象
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
// 定义Map的value值
message MapVaule {
string mapValue = 1;
}
3.1.1,一个字段由以下部分组成:
规则 类型 字段名=标识号; [// 注释]
3.1.1.1,指定字段规则
所指定的消息字段修饰符必须是如下之一:
required | 一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的 |
optional | 消息格式中该字段可以有0个或1个值(不超过1个) |
repeated | 在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List |
由于一些历史原因,基本数值类型的repeated的字段并没有被尽可能地高效编码。在新的代码中,用户应该使用特殊选项[packed=true]来保证更高效的编码。如:
repeated int32 samples = 4 [packed=true];
required是永久性的:在将一个字段标识为required的时候,应该特别小心。如果在某些情况下不想写入或者发送一个required的 字段,将原始该字段修饰符更改为optional可能会遇到问题——旧版本的使用者会认为不含该字段的消息是不完整的,从而可能会无目的的拒绝解析。在这 种情况下,你应该考虑编写特别针对于应用程序的、自定义的消息校验函数。Google的一些工程师得出了一个结论:使用required弊多于利;他们更 愿意使用optional和repeated而不是required。当然,这个观点并不具有普遍性。
3.1.1.2,指定字段类型
在上面的例子中,所有字段都是标量类型:两个整型(page_number和result_per_page),一个string类型(query)。当然,你也可以为字段指定其他的合成类型,包括枚举(enumerations)或其他消息类型。
一个标量消息字段可以含有一个如下的类型——该表格展示了定义于.proto文件中的类型,以及与之对应的、在自动生成的访问类中定义的类型:
3.1.1.3,分配标识号
正如上述文件格式,在消息定义中,每个字段都有唯一的一个标识符。这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改 变。注:[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。切记:要为将来有可能添加的、频繁出现的标识号预留一些标识号。
最小的标识号可以从1开始,最大到229 - 1, or 536,870,911。不可以使用其中的[19000-19999]的标识号, Protobuf协议实现中对这些进行了预留。如果非要在.proto文件中使用这些预留标识号,编译时就会报警。
3.1.1.4,添加注释
向.proto文件添加注释,可以使用C/C++/java风格的双斜杠(//) 语法格式,如:
3.1.2,从.proto文件生成了什么?
语言 | 产生文件 |
C++ | 编译器会为每个.proto文件生成一个.h文件和一个.cc文件,.proto文件中的每一个消息有一个对应的类。 |
Java | 编译器为每一个消息类型生成了一个.java文件,以及一个特殊的Builder类(该类是用来创建消息类接口的)。 |
Python | 有点不太一样——Python编译器为.proto文件中的每个消息类型生成一个含有静态描述符的模块,,该模块与一个元类(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。 |
go | 编译器会位每个消息类型生成了一个.pd.go文件。 |
Ruby | 编译器会为每个消息类型生成了一个.rb文件。 |
javaNano | 编译器输出类似域java但是没有Builder类 |
Objective-C | 编译器会为每个消息类型生成了一个pbobjc.h文件和pbobjcm文件,.proto文件中的每一个消息有一个对应的类。 |
C# | 编译器会为每个消息类型生成了一个.cs文件,.proto文件中的每一个消息有一个对应的类。 |
3.1.3,枚举
如你所见,Corpus枚举的第一个常量映射为0:每个枚举类型必须将其第一个类型映射为0,这是因为:
必须有有一个0值,我们可以用这个0值作为默认值。
这个零值必须为第一个元素,为了兼容proto2语义,枚举类的第一个值总是默认值。
你可以通过将不同的枚举常量指定位相同的值。如果这样做你需要将allow_alias设定位true,否则编译器会在别名的地方产生一个错误信息。
3.2,使用protoc编译器进行编译
//SRC_DIR .proto文件存放目录
//--cpp_out 指示编译器生成C++代码,DST_DIR为生成文件存放目录
//game.proto 待编译的协议文件
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/game.proto
3.2.1,导出C++包
protoc --cpp_out=./ config.proto
报错:
[libprotobuf WARNING google/protobuf/compiler/parser.cc:637] No syntax specified for the proto file: config.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.) |
![]() |
3.2.2,导出java包
protoc --java_out=./ ./config.proto
3.2.3,导出python包
protoc --python_out=./ ./config.proto
3.3,编译代码
g++ -std=c++11 addressbook.pb.cc write_data.cpp -o write_data.out -lprotobuf `pkg-config --cflags --libs protobuf`
g++ -std=c++11 addressbook.pb.cc read_data.cpp -o read_data.out -lprotobuf `pkg-config --cflags --libs protobuf`