1. protobuf安装
下载https://github.com/google/protobuf/releases ##Source code (zip)##
./autogen.sh
./configure
make
make check
make install
当安装有anaconda时,系统会默认调用anaconda中的protoc,所以需要手动将anaconda中的protoc替换为编译的版本
which protoc // 查看protoc安装位置
whereis protoc // 查看所有protoc安装位置
protoc--version //查看protoc版本
2. protoc使用
proto文件
syntax="proto3";
package tutorial;
message Person
{
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType
{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber
{
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phone = 4;
}
生成对应的c++文件
protoc --cpp_out=./ ./Person.proto
代码
#include <iostream>
#include <fstream>
#include <fcntl.h>
#include <zconf.h>
#include <tiff.h>
#include "Person.pb.cc"
using namespace std;
void write_person() {
tutorial::Person sr;
sr.set_name("mike");
sr.set_email("dsa@sda.com");
sr.set_id(32);
tutorial::Person_PhoneNumber *person_phoneNumber = sr.add_phone();
person_phoneNumber->set_number("1111");
person_phoneNumber->set_type(tutorial::Person::MOBILE);
int fd = open("./pb.xxx", O_CREAT | O_TRUNC | O_RDWR, 0644);
sr.SerializeToFileDescriptor(fd);
close(fd);
}
void read_person() {
int fd = open("./pb.xxx", O_RDONLY);
tutorial::Person person;
if (person.ParseFromFileDescriptor(fd)) {
cout << "name:" << person.name() << endl;
cout << "email:" << person.email() << endl;
cout << "id:" << person.id() << endl;
cout << "phone:" << person.phone(0).number() << endl;
}
}
int main(int argc, char *argv[]) {
write_person();
read_person();
return 0;
}
3. 语法
指定字段规则
所指定的消息字段修饰符必须是如下之一:
- singular:一个格式良好的消息应该有0个或者1个这种字段(但是不能超过1个)。
-
repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。
标量数值类型
一个标量消息字段可以含有一个如下的类型——该表格展示了定义于.proto文件中的类型,以及与之对应的、在自动生成的访问类中定义的类型:
.proto Type | Notes | C++ Type | Java Type | Python Type[2] | Go Type | Ruby Type | C# Type | PHP Type |
---|---|---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | double | float | |
float | float | float | float | float32 | Float | float | float | |
int32 | 使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int | integer |
uint32 | 使用变长编码 | uint32 | int | int/long | uint32 | Fixnum 或者 Bignum(根据需要) | uint | integer |
uint64 | 使用变长编码 | uint64 | long | int/long | uint64 | Bignum | ulong | integer/string |
sint32 | 使用变长编码,这些编码在负值时比int32高效的多 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int | integer |
sint64 | 使用变长编码,有符号的整型值。编码时比通常的int64高效。 | int64 | long | int/long | int64 | Bignum | long | integer/string |
fixed32 | 总是4个字节,如果数值总是比总是比228大的话,这个类型会比uint32高效。 | uint32 | int | int | uint32 | Fixnum 或者 Bignum(根据需要) | uint | integer |
fixed64 | 总是8个字节,如果数值总是比总是比256大的话,这个类型会比uint64高效。 | uint64 | long | int/long | uint64 | Bignum | ulong | integer/string |
sfixed32 | 总是4个字节 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int | integer |
sfixed64 | 总是8个字节 | int64 | long | int/long | int64 | Bignum | long | integer/string |
bool | bool | boolean | bool | bool | TrueClass/FalseClass | bool | boolean | |
string | 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。 | string | String | str/unicode | string | String (UTF-8) | string | string |
bytes | 可能包含任意顺序的字节数据。 | string | ByteString | str | []byte | String (ASCII-8BIT) | ByteString | string |
- 在java中,无符号32位和64位整型被表示成他们的整型对应形似,最高位被储存在标志位中。
- 对于所有的情况,设定值会执行类型检查以确保此值是有效。
- 64位或者无符号32位整型在解码时被表示成为ilong,但是在设置时可以使用int型值设定,在所有的情况下,值必须符合其设置其类型的要求。
- python中string被表示成在解码时表示成unicode。但是一个ASCIIstring可以被表示成str类型。
- Integer在64位的机器上使用,string在32位机器上使用
枚举
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
- 如你所见,Corpus枚举的第一个常量映射为0:每个枚举类型必须将其第一个类型映射为0,这是因为:
- 必须有有一个0值,我们可以用这个0值作为默认值。
-
这个零值必须为第一个元素,为了兼容proto2语义,枚举类的第一个值总是默认值。