Protobuf 笔记

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 TypeNotesC++ TypeJava TypePython Type[2]Go TypeRuby TypeC# TypePHP Type
double doubledoublefloatfloat64Floatdoublefloat
float floatfloatfloatfloat32Floatfloatfloat
int32使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代int32intintint32Fixnum 或者 Bignum(根据需要)intinteger
uint32使用变长编码uint32intint/longuint32Fixnum 或者 Bignum(根据需要)uintinteger
uint64使用变长编码uint64longint/longuint64Bignumulonginteger/string
sint32使用变长编码,这些编码在负值时比int32高效的多int32intintint32Fixnum 或者 Bignum(根据需要)intinteger
sint64使用变长编码,有符号的整型值。编码时比通常的int64高效。int64longint/longint64Bignumlonginteger/string
fixed32总是4个字节,如果数值总是比总是比228大的话,这个类型会比uint32高效。uint32intintuint32Fixnum 或者 Bignum(根据需要)uintinteger
fixed64总是8个字节,如果数值总是比总是比256大的话,这个类型会比uint64高效。uint64longint/longuint64Bignumulonginteger/string
sfixed32总是4个字节int32intintint32Fixnum 或者 Bignum(根据需要)intinteger
sfixed64总是8个字节int64longint/longint64Bignumlonginteger/string
bool boolbooleanboolboolTrueClass/FalseClassboolboolean
string一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。stringStringstr/unicodestringString (UTF-8)stringstring
bytes可能包含任意顺序的字节数据。stringByteStringstr[]byteString (ASCII-8BIT)ByteStringstring

参考Protocol Buffer 编码

  1. 在java中,无符号32位和64位整型被表示成他们的整型对应形似,最高位被储存在标志位中。
  2. 对于所有的情况,设定值会执行类型检查以确保此值是有效。
  3. 64位或者无符号32位整型在解码时被表示成为ilong,但是在设置时可以使用int型值设定,在所有的情况下,值必须符合其设置其类型的要求。
  4. python中string被表示成在解码时表示成unicode。但是一个ASCIIstring可以被表示成str类型。
  5. 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语义,枚举类的第一个值总是默认值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值