c++使用proto文件方法简介

来源:互联网 发布:java main函数 多线程 编辑:程序博客网 时间:2024/05/23 19:51

转自:http://blog.csdn.net/lijinqi1987/article/details/52067626
GoogleProtocol Buffers 简称 Protobuf,是 Google 公司内部的混合语言数据标准.它提供一种轻量,高效的结构化数据存储结构.

简介
为什么要使用protobuf?

  1. 官方文档中提到一些protobuf的优点, protobuf灵活高效的结构化数据存储格式.方便用于序列化, 适合做RPC的数据交换.

  2. 相比 XML , protobuf 比 XML 更小、更快、更简单.仅需要写一个 *.proto 文件描述需要的数据结构, protobuf会帮助你实现相关类和方法(自动化多好!).

  3. 目前提供 C++, Java, Python, Go, C#等多种语言 的API

安装
在ubuntu上一键安装

sudoapt-get install protobuf-compiler

定义proto文件
定义proto文件较为简单,给每个结构体数据定义一个message,然后给结构体中的每个数据添加一个类型和名称,例如,想要定义一个address.proto文件

[plain] view plain copy 在CODE上查看代码片派生到我的代码片

package tutorial;  message Person {    required string name = 1;    required int32 id = 2;    optional string email = 3;    enum PhoneType {      MOBILE = 0;      HOME = 1;      WORK = 2;    }    message PhoneNumber {      required string number = 1;      optional PhoneType type = 2 [default = HOME];    }    repeated PhoneNumber phone = 4;  }  message AddressBook {    repeated Person person = 1;  }  

有如你所见,消息格式很简单,每个消息类型拥有一个或多个特定的数字字段,每个字段拥有一个名字和一个值类型。值类型可以是数字(整数或浮点)、布尔型、字符串、原始字节或者其他ProtocolBuffer类型,还允许数据结构的分级。你可以指定可选字段,必选字段和重复字段。

一旦你定义了自己的报文格式(message),你就可以运行ProtocolBuffer编译器,将你的 .proto 文件编译成特定语言的类。这些类提供了简单的方法访问每个字段(像是 query()和 set_query() ),像是访问类的方法一样将结构串行化或反串行化。

编译proto文件

现在已经拥有了 .proto文件,下一步就是编译生成相关的访问类。运行编译器 protoc 编译你的 .proto文件。

  1. 如果还没安装编译器则下载并按照README的安装。

  2. 运行编译器,指定源目录和目标目录,定位你的 .proto文件到源目录,然后执行:

protoc-I=SRCDIRcppout=DST_DIRaddressbook.proto

此操作生成c++格式的proto文件,如果想生成Python、java等类型的,把cpp换成python、java等即可,该操作生成如下两个文件:

addressbook.pb.h 定义了c++的头文件

addressbook.pb.cc 包含了类的实现

protocol buffer API
编译后的name、id、emal、和phone有如下方法:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

// name    inline bool has_name() const;    inline void clear_name();    inline const ::std::string& name() const;    inline void set_name(const ::std::string& value);    inline void set_name(const char* value);    inline ::std::string* mutable_name();    // id    inline bool has_id() const;    inline void clear_id();    inline int32_t id() const;    inline void set_id(int32_t value);    // email    inline bool has_email() const;    inline void clear_email();    inline const ::std::string& email() const;    inline void set_email(const ::std::string& value);    inline void set_email(const char* value);    inline ::std::string* mutable_email();    // phone    inline int phone_size() const;    inline void clear_phone();    inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >& phone() const;    inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >* mutable_phone();    inline const ::tutorial::Person_PhoneNumber& phone(int index) const;    inline ::tutorial::Person_PhoneNumber* mutable_phone(int index);    inline ::tutorial::Person_PhoneNumber* add_phone();  如你所见,获取字段的方法都是字段名称的小写,如[cpp] view plain copy 在CODE上查看代码片派生到我的代码片inline const ::std::string& name()const;  inline int32_t id()const;  inline const ::std::string& email()const;  inline const ::tutorial::Person_PhoneNumber& phone(int index) const;  

设置字段名称的方法都已set_开头,singular (required or optional) 类型的字段有has_开头的方法,如果该字段已经设置了,那么该方法返回true

最后,每个字段都有一个clear_方法来把字段复位为空状态

数字类型的字段id只有基本的设置字段的方法,string型的字段name和email有几个其他的方法,mutable_开头的方法让你得到一个直接指向string类型的指针,及时email未被设置,你也可以调用mutable_email(),它将会自动初始化为一个空的string。如果字段在调用这个方法之前没有被设置,那么返回的字符串将为空(而不是缺省值)。调用这个方法后,has_foo()返回 true,foo()返回被写入到字符串(foo)中的任何值。通过调用 Clear()或 clear_foo()清除此指针。

Repeated类型的字段有一些特殊的方法

_size:检查有多少个字段

使用index来获取特定的字段

更新一个已经存在的字段

add_方法添加一个新的字段

生成的代码包含一个PthonType枚举,可以通过Person::PthonType或者它们的值Person::MOBILE, Person::HOME,和Person::WORK来调用它们.

标准消息方法
每个消息还包括一些其他方法用来检查和操作整个消息

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
bool IsInitialized() const; //检查是否所有的requied类型的消息都被设置了
string DebugString() const;//返回消息的一个可读类型,debug时很有用
void CopyFrom(const Person& from);//用给定的值来覆盖消息
void Clear();//把所有元素置回空状态

解析和序列化
最终,protocol buffer类有使用二进制格式来读写消息的方法:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
bool SerializeToString(string* output) const;//序列化消息并把字节存储在给定的string类型中,注意字节是二进制类型,而不是text类型,我们只是使用string类型作为一个转换容易
bool ParseFromString(const string& data);//从string中解析消息
bool SerializeToOstream(ostream* output)const;//把消息写入一个给定的c++ostream中
bool ParseFromIstream(istream* input);//从一个给定的c++ istream中解析消息

0 0
原创粉丝点击