Ggoogle Protocol Buffer的使用 (基于C++语言)
首先说明的是Protocol Buffle是灵活高效的.它的一个很好的优点(很重要的,我认为)就是后向兼容性——当我们扩展了了.proto文件后,我们照样可以用它来读取之前生成的文件。
之前已经写了关于.proto文件定义的相关知识,见http://www.cnblogs.com/yinheyi/p/6080244.html,现在写基于C语言的Ggoogle Protocol Buffer的使用.
下面的例子,为了实现我们的一个应用 :通讯录,它包含一个人的名字,ID,电子邮件,联系电话,并实现存储与读取。
第一步,定义一个 .proto 文件
/* 首先是一个 package名称的声明,它的作用就是防止出现名字的冲突; 当生成C++代码的时候,对应的pacage名称会生成一个相同名字的命名空间。 */ package tutorial; message Person { required ; required int32 id = ; optional ; enum PhoneType { MOBILE = ; HOME = ; WORK = ; } message PhoneNumber { required ; optional PhoneType type = [default = HOME]; } repeated PhoneNumber phone = ; } message AddressBook { repeated Person person = ; }
第二步:用生成protobuf 编译器编译写的.proto文件。
命令为:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto其中,-I=$SRC_DIR,表示指明源文件的目录,也可以用 –proto_path, 它们是等价的。当我们有import .proto文件时,它也会从这里指定的目录去搜索。
-cpp_out=$DST_DIR, –cpp_out,表示我们输出的是C++类型的代码,$DST_DIR表示输出的目录。
后面的$SRC_DIR/addressbook.proto表示我们经编译的源文件,它在-I指定的目录下的哦;
运行完命令后,会输出.pb.cc文件与.pb.h文件。
例如,我的.proto文件名为:tutorial.addressbook.proto, 那么我生成的文件为: tutorial.addressbook.pb.h和tutorial.addressbook.pb.cc文件。
第三步,在我们写的程序中调用Protocol Buffe的C++的API来使用我们定义的AddressBook类。
在我们想知道怎么使用它的时候,不防先看看生成的文件里面是什么,让我们打开 tutorial.addressbook.bh.h文件,比如Person类开定义,我们会发现如下的代码:
// accessors ------------------------------------------------------- // required string name = 1; 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 void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); inline ::std::string* release_name(); inline void set_allocated_name(::std::string* name); // required int32 id = 2; inline bool has_id() const; inline void clear_id(); ; inline ::google::protobuf::int32 id() const; inline void set_id(::google::protobuf::int32 value); // optional string email = 3; 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 void set_email(const char* value, size_t size); inline ::std::string* mutable_email(); inline ::std::string* release_email(); inline void set_allocated_email(::std::string* email); // repeated .tutorial.Person.PhoneNumber phone = 4; inline int phone_size() const; inline void clear_phone(); ; inline const ::tutorial::Person_PhoneNumber& phone(int index) const; inline ::tutorial::Person_PhoneNumber* mutable_phone(int index); inline ::tutorial::Person_PhoneNumber* add_phone(); inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >& phone() const; inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >* mutable_phone();上面它就是定义了访问Person类成员函数的方法。如,可以通过name()方法得到它的值。可以通过set_name()方法设置它的值。 通过has_name()判断是否有这个值,通过clear_name()清空它的值。
另外,string类型也numeic类型相比较,还多出了几项,如通过mutable_name()可以得到指针的。
还有,对于repeated的关键字的来说 ,又有一些不同。如,可以通过name_size()得到有多个项(就是它因为可以重复嘛,重复了多少次呢),也可以通过 index 得到特定的第几个的值,等等。
如果想要详细看的话,可以https://developers.google.com/protocol-buffers/docs/reference/cpp-generated看这里哈。
它,也提供了可以能message进行全局操作的标准message 方法, 如:
bool IsInitialized() const; 用于检查是不是所有的required 字段已经初始化、
string DebugString() const; 返回一个人可以读懂的representation of the message,在debug时,很有用的。
void CopyFrom(const Person& from), 用另一个类为一个类赋值;
void Clear() 把类中的所有元素的值变为空状态(unset)
解析与序列化(就是读与写啦)
如:bool SerializeToString(string* output) const ,序列化我们的Message,并把得到的bytes放到string类型中。(注意,这里的bytes仍然是二进制文件,我们只不过使用string作为一个容器来装我们的bytes.)
bool ParseFromString(const string& data); 解析;
bool SerializeToOstream(ostream* output) const;
bool ParseFromIstream(istream* input);
编写我们自己的程序:
写文件的程序:
#include<iostream>
#include<fstream>
#include<string>
$include "tutorial.addressbook.pb.h"
using namespace std;
//定义一个函数,用于设置person对象的值;
//参数为: 一个person 对象的指针; 返回为空;
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number :";
int id;
cin >> id;
person->set_id(id);
cin.ignore(, '\n') //作用:用于清除缓冲区的内容,防止对下次输入产生影响.
cout << "Enter name: ";
getline(cin, *person->mutable_name()); //mutable_name()返回一个指针,再加上*,要干什么?看来要补补getline()函数了;
cout<< "Enter email address(blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number(number);
cout <<"Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type =="work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << "Unknown phone type. Using default." <<endl;
}
}
}
int main(int argc, char* argv[]) {
GOOGLE_PROTOBUF_VERIFY_VERSION; //这是一个宏命令,用于检查看看用的protobuf的库是否兼容;最好加上它;
) {
cerr << ] << "ADDRESS_BOOK_FILE" << endl;
;
}
tutorial::AddressBook address_book;
//读文件,如果不存在,就创建;
fstream input(argv[], ios::in | ios::binary);
if (!input) {
cout << argv[] << ":File not found, Creating a new file." <<endl;
} else if (!address_book.ParseFromeIstream(&input)) {
cerr << "Failed to parse address book." << endl;
;
}
//增加address;
PromptForAddress(address_book.add_person());
//写放盘中;
fstream output(argv[], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
;
}
//用于把全局的由libprotobuf申请的对象空间;
google::protobuf::ShutdownProtobufLibrary();
;
}
GOOGLE_PROTOBUF_VERIFY_VERSION是一个宏命令,我们最好加上它,因为它的作用可以用于检查我们的library是否不兼的问题。如果 你不想加,也没有办法哦;
ShutdownProtobufLibrary() 它的作用为:delete any global objects that were allocated by the Protocol Buffer library.通常或许我们不用加它,因为我们运行完我们的程序,我们就退出了,然后操作系统会回收内存的。但是如果不加的话,当我们用内存泄漏检查器检查程序时,它会说内存泄漏的。
读取文件的程序:
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
; i < address_book.person_size(); i++) {
const tutorial::Person& person = address_book.person(i);
cout << "Person ID: " << person.id() << endl;
cout << " Name: " << person.name() << endl;
if (person.has_email()) {
cout << " E-mail address: " << person.email() << endl;
}
; j < person.phone_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phone(j);
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
cout << " Mobile phone #: ";
break;
case tutorial::Person::HOME:
cout << " Home phone #: ";
break;
case tutorial::Person::WORK:
cout << " Work phone #: ";
break;
}
cout << phone_number.number() << endl;
}
}
}
// Main function: Reads the entire address book from a file and prints all
// the information inside.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
) {
cerr << ] << " ADDRESS_BOOK_FILE" << endl;
;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[], ios::in | ios::binary);
if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
;
}
}
ListPeople(address_book);
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
;
}
很简单吧;
另外,说一点代码风格:
1. 消息名字:大写字母开头的驼峰表示法表示消息名称,如:SongServerRequest。
2. 字段名: 使用小写字母+下划线分隔表示字段名,如:song_name。
message SongServerRequest {
required ;
}
3. 枚举类型:大写字母开头的驼峰表示法表示枚举名称,使用大写字母+下划线表示值
enum Foo {
FIRST_VALUE = ;
SECOND_VALUE = ;
}
参考:
https://developers.google.com/protocol-buffers/docs/cpptutorial
https://my.oschina.net/macwe/blog/157862
最后,如果你觉得以上内容对你提供了实质的帮助, 如果你有钱的话,如果你愿意的话,可以打赏一下我这个穷学生哦,资助我买几本书.
钱也不用太多哦, 您可以选择:2毛,5毛、1元。(靠知识创造价值, 靠知识改变生活 ——爱你们的杰克船长,么么哒)

Ggoogle Protocol Buffer的使用 (基于C++语言)的更多相关文章
- gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(下)
第一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html gRPC in ASP.NET Core 3.x -- Protocol Buf ...
- gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(上)
上一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html 建立Go项目 在GOPATH的src下面建立一个文件夹 protobuf-go, ...
- Protocol Buffer技术详解(语言规范)
Protocol Buffer技术详解(语言规范) 该系列Blog的内容主体主要源自于Protocol Buffer的官方文档,而代码示例则抽取于当前正在开发的一个公司内部项目的Demo.这样做的目的 ...
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.google.co ...
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端--转载
原文地址:http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.goog ...
- 在 go/golang语言中使用 google Protocol Buffer
怎么在go语言中实用google protocol Buffer呢? 现在的潮流趋势就是一键搞定,跟ubuntu安装软件一样 go get code.google.com/p/goprotobuf/{ ...
- 一个基于protocol buffer的RPC实现
Protocol Buffer仅仅是提供了一套序列化和反序列化结构数据的机制,本身不具有RPC功能,但是可以基于其实现一套RPC框架. Services protocol buffer的Service ...
- 从零开始山寨Caffe·伍:Protocol Buffer简易指南
你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...
- Google Protocol Buffer 的使用和原理[转]
本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...
随机推荐
- 详解依赖注入(DI)和Ioc容器
简单的来说,关键技术就是:注册器模式. 场景需求 我们知道写一个类的时候,类本身是有个目的的,类里面有很多方法,每个方法搞定一些事情:我们叫这个类为主类. 另外这个主类会依赖一些其他类的帮忙,我们叫这 ...
- sql server中sql语句中单引号怎么转义?【转】
sql server有两个转义符: ' 默认情况下, '是字符串的边界符, 如果在字符串中包含', 则必须使用两个', 第1个'就是转义符 另一个转义符是" 当SET QUOTED_IDEN ...
- IIS7配置PHP 报错 "对找不到的文件启用文件监视"
原文 IIS7配置PHP5.4报错对找不到的文件启用文件监视怎么解决? 案例环境:windows2008+IIS7+PHP5.4+ZEND LOADER用户在配置后遇到报错:错误摘要 HTTP 错误 ...
- tomcat access log 参数
%a - 客户端IP地址 %A - 本机IP地址 %b - 发送字节数,不含HTTP头 如果为空是 '-' %B - 同上 %h - 客户端机器名 (如果connector的enableLookup ...
- 史上最全的SpringMVC学习笔记
SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于Spring ...
- JAVA多线程实现的三种方式
JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...
- Hibernate Validator验证标签说明
Hibernate Validator是JSR-303的一个实现. 在FormBean里添加Hibernate Validator的注解,与定义一个校验类的做法相比.注解更加简洁.灵活. Bean V ...
- [原创]java WEB学习笔记95:Hibernate 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- .NET MVC3中扩展一个HtmlHelper方法CheckBoxList
MVC中有DropDownList方法,挺好用,可是最常用的需求,一组checkboxlist咋没个类似方法呢?郁闷之余,自己做一个吧,直接上代码 public static MvcHtmlStrin ...
- C#:判断软件运行的环境是否是Pad(PC)
一.需求:Pad上显示某功能块,PC机上隐藏. 二.方法:从外围设备获取值判断是否是Pad. 三.具体参考代码如下: 1.外围设备值类型如下: public enum ChassisTypes { O ...