首先说明的是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)

想了解更多,可以看https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message.html#Message

解析与序列化(就是读与写啦)

如: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);

更多见:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message.html#Message

编写我们自己的程序:

写文件的程序:

 #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++语言)的更多相关文章

  1. 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 ...

  2. gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(上)

    上一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html 建立Go项目 在GOPATH的src下面建立一个文件夹 protobuf-go, ...

  3. Protocol Buffer技术详解(语言规范)

    Protocol Buffer技术详解(语言规范) 该系列Blog的内容主体主要源自于Protocol Buffer的官方文档,而代码示例则抽取于当前正在开发的一个公司内部项目的Demo.这样做的目的 ...

  4. Hadoop基于Protocol Buffer的RPC实现代码分析-Server端

    http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.google.co ...

  5. Hadoop基于Protocol Buffer的RPC实现代码分析-Server端--转载

    原文地址:http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.goog ...

  6. 在 go/golang语言中使用 google Protocol Buffer

    怎么在go语言中实用google protocol Buffer呢? 现在的潮流趋势就是一键搞定,跟ubuntu安装软件一样 go get code.google.com/p/goprotobuf/{ ...

  7. 一个基于protocol buffer的RPC实现

    Protocol Buffer仅仅是提供了一套序列化和反序列化结构数据的机制,本身不具有RPC功能,但是可以基于其实现一套RPC框架. Services protocol buffer的Service ...

  8. 从零开始山寨Caffe·伍:Protocol Buffer简易指南

    你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...

  9. Google Protocol Buffer 的使用和原理[转]

    本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...

随机推荐

  1. 深度学习笔记(四)VGG14

    Very Deep Convolutional Networks for Large-Scale Image Recognition 1. 主要贡献 本文探究了参数总数基本不变的情况下,CNN随着层数 ...

  2. RAC One Node转换为RAC

    1.查看状态 [oracle@rone1 ~]$ srvctl config database -d rone Database unique name: rone Database name: ro ...

  3. linux 下查看系统资源和负载,以及性能监控

    1,查看磁盘   df -h   2,查看内存大小   free   free [-m|g]按MB,GB显示内存   vmstat   3,查看cpu   cat /proc/cpuinfo   只看 ...

  4. struts action和jsp之间的传值

    一.jsp对Action传值 提交表单即可,Action的属性必须和表单的标签名字相同 二.Action对jsp传值: (1)利用session,(个人推荐) action中ActionContext ...

  5. android webview 底层实现的逻辑

    其实在不同版本上,webview底层是有所不同的. 先提供个地址给大家查:http://grepcode.com/file/repository.grepcode.com/java/ext/com.g ...

  6. Java集合---ArrayList的实现原理

    目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除                 6) 调整数组容量 ...

  7. 十二、Java基础---------异常处理机制

    异常 异常 异常就是程序在运行时产生的异常情况. 异常的由来 问题也是现实生活中的具体事物,也可以通过java 类的形式进行描述,并封装成对象.异常就是java 对不正常情况进行描述后的对象的体现. ...

  8. 数据可视化:Echart中k图实现动态阈值报警及实时更新数据

    1 目标 使用Echart的k图展现上下阈值,并且当真实值超过上阈值或低于下阈值时候,标红报警. 2 实现效果 如下:

  9. Create Your Tab and LayerTabMenu In Katana

    感谢 http://tool.lu/pyc/ 这个牛逼的网站能反编译pyc...他妈的Katana太他妈无耻了,竟然不让自定义加Node Tab Content....只能反编译他的东西了... 研究 ...

  10. android手电筒(摇一摇也可开启手电筒)

    package com.firefly.myflashlight; import android.app.Activity; import android.hardware.Camera; impor ...