Protocol Buffer学习教程之类库应用(四)

来源:互联网 发布:棉柔巾 知乎 编辑:程序博客网 时间:2024/05/17 02:05

 

Protocol Buffer学习教程之类库应用()

 

 

此教程是通过一个简单的示例,给C++开发者介绍一下如何使用protocol buffers编程,主要包括以下几部分:

定义一个.proto文件

如何使用protocol buffer编译器生成C++类文件

如何使用Protocol buffer api读写消息

 

这并不是分全面的protocol bufferC++编程手册,更详尽的资料请参见Protocol Buffer Language Guide(https://developers.google.com/protocol-buffers/docs/proto), the C++ API Reference (https://developers.google.com/protocol-buffers/docs/reference/cpp/index.html), the C++ Generated Code Guide (https://developers.google.com/protocol-buffers/docs/reference/cpp-generated),the Encoding Reference (https://developers.google.com/protocol-buffers/docs/encoding)

 

定义一个.proto文件

创建一个文本文件,重命名为addressbook.proto”,注意扩展名为“.proto”。

syntax = "proto2";

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 phones = 4;

}

 

message AddressBook {

  repeated Person people = 1;

}

生成类文件

然后通过前面第三部份介绍生成的proto.exe编译器,生成C++类文件,在命令行中,cdproto.exe根目录,执行以下命令:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

然后将生成两个文件addressbook.pb.haddressbook.pb.cc。打开头文件,能看到以下内容:

// 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();

  // phones
  inline int phones_size()const;
  inline void clear_phones();
  inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >& phones()const;
  inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >* mutable_phones();
  inline const ::tutorial::Person_PhoneNumber& phones(int index)const;
  inline ::tutorial::Person_PhoneNumber* mutable_phones(int index);
  inline ::tutorial::Person_PhoneNumber* add_phones();

方法分析

可以看到,每个段都有读、写方法,读方法就是段名,没有加前后缀,而写方法以set_前缀开头,可能有多个对应不同的设置方式,同时还有清空clear_前缀的方法,has_前缀的方法是用于判断某个段是否存在,即赋过值。而mutable_前缀的方法,是直接给返回对象的指针。

对于repeated字段,会发现有更多的接口,repeated字段相当于队列数据,里面存储的是同一类型的数据。

_size后缀的方法,用于统计队列里的元素数量。

同时提供直接通过index索引来读、写元素的方法,段名加元素索引的方法进行读写。写通过索引,返回对应元素的指针,然后通过指针对元素进行修改操作。

还有一个add_前缀方法,这个方法相当于给当前队列增加一个元素空间,它返回新增的元素空间的指针。可以通过此指针对它进行赋值操作。

 

标准方法

bool IsInitialized() const;检验是否必须赋值的段都赋值了。

string DebugString() const;返回一个对于消息可读的描述,对于调试非常有用。

void CopyFrom(const Person& from);从提供的消息对象复制一个副本。

void Clear();清空消息中的所有段到空的状态。

 

序列化与反序列化

bool SerializeToString(string* output) const;序列化消息并以字节流的方式存储到string类型的output中,它是二进制的,并不是text文本,使用string类只是为了方便。

bool ParseFromString(const string& data);对提供的data数据进行序列化成消息对象。

bool SerializeToOstream(ostream* output) const;反序列化成C++的流

bool ParseFromIstream(istream* input);把流序列化成消息对象。

 

填充消息

#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
  cout << "Enter person ID number: ";
  int id;
  cin >> id;
  person->set_id(id);
  cin.ignore(256,'\n');

  cout << "Enter name: ";
  getline(cin, *person->mutable_name());

  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_phones();
    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;
    }
  }
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
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;

  if (argc !=2) {
    cerr << "Usage:  " << argv[0] <<" ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!input) {
      cout << argv[1] <<": File not found.  Creating a new file." << endl;
    } else if (!address_book.ParseFromIstream(&input)) {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  // Add an address.
  PromptForAddress(address_book.add_people());

  {
    // Write the new address book back to disk.
    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
    if (!address_book.SerializeToOstream(&output)) {
      cerr << "Failed to write address book." << endl;
      return -1;
    }
  }

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

 

读消息

#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) {
  for (int i =0; i <address_book.people_size(); i++) {
    const tutorial::Person& person = address_book.people(i);

    cout << "Person ID: " <<person.id() << endl;
    cout << "  Name: " <<person.name() << endl;
    if (person.has_email()) {
      cout << "  E-mail address: " <<person.email() << endl;
    }

    for (int j =0; j <person.phones_size(); j++) {
      const tutorial::Person::PhoneNumber& phone_number = person.phones(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;

  if (argc !=2) {
    cerr << "Usage:  " << argv[0] <<" ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!address_book.ParseFromIstream(&input)) {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  ListPeople(address_book);

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

关于完整的API接口说明,请查看:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message#MessageFactory

 

 

 

 

 

 

 

 

 

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 staub珐琅铸铁锅食谱 清乾隆珐琅彩瓷器鉴定 珐琅锅开锅 乾隆御制珐琅彩 康熙御制珐琅彩碗 珐琅锅食谱 珐琅铸铁锅好不好 铜胎画珐琅鼻烟壶 珐琅锅品牌 珐琅瓷铸铁锅 画珐琅 珐琅锅煲仔饭 珐琅是什么材质 灵珑 珑组词 祖玛珑 玖珑财富 什么珑奇什么 小舅舅珑公子 珑骧包属于什么档次 珑怎么读 珑组词语 珑公子 恒大玖珑湾 龙湖双珑原著 珑的组词 珑公子作品 玫珑瓜 凉森珑梦 珑拼音 龙光玖珑湖 珑词语 珑的拼音 祖玛珑香水属于什么档次 珑氏创始人龙大大个人资料 珑湖湾 嘉地珑墅 雅居乐锦城 融创绿城 佛山水岸珑庭