没有前言了

# 1. 提供接口

# 属性接口

在编译完成后的.h 文件中,有非常多的方法供调用。
上一次定义了 addressbook.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 文件编译成的.h 文件中有非常多的接口和方法。先来看关于数据项的一些接口:

//name, 主要以他为例,下面说明每个方法的作用
  //has_xxx (), 用来判断该值是否已经赋过值
  inline bool has_name() const;
  //clear_xxx (), 用来判断该值是否已经赋过值
  inline void clear_name();
  //xxx (), 获取对应属性的值,即我们一般使用的 get 方法
  inline const ::std::string& name() const;
  //set_xxx (), 修改对应属性的值,此处参数是 string,c++11 中会多一个这个方法
  inline void set_name(const ::std::string& value);
  //set_xxx (), 修改对应属性的值,此处参数是 char*
  inline void set_name(const char* value);
  //mutable_xxx (), 返回一个直接指向对象对应属性的指针,可以通过这个指针改变属性值
  inline ::std::string* mutable_name();
  //id,int 型的只有 4 个基本方法
  inline bool has_id() const;
  inline void clear_id();
  inline int32_t id() const;
  inline void set_id(int32_t value);
  //email, 同 name
  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,phones 是一个 repeated 的数据项,所有会有一些特有的方法
  //xxx_size (), 数据条目数
  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();
  //xxx (int index) 和 mutable_xxx (), 通过 index 去访问某一个 repeated 的数据项
  inline const ::tutorial::Person_PhoneNumber& phones(int index) const;
  inline ::tutorial::Person_PhoneNumber* mutable_phones(int index);
  //add_xxx (), 添加一条数据
  inline ::tutorial::Person_PhoneNumber* add_phones();

# message 接口

每个 message 生成类中会包含以下接口:

// 判断是否所有 required 的数据项都赋值过了
bool IsInitialized() const;
// 返回一个包含各个属性的可读字符串,用于调试
string DebugString() const;
// 用另一个 message 类给自己赋值
void CopyFrom(const Person& from);
// 清空所有值
void Clear();

# 序列化接口

// 序列化至 output 字符串
bool SerializeToString(string* output) const;
// 使用字符串给自己赋值
bool ParseFromString(const string& data);
// 序列化至输出流
bool SerializeToOstream(ostream* output) const;: writes the message to the given C++ ostream.
// 使用输入流给自己赋值
bool ParseFromIstream(istream* input);: parses a message from the given C++ istream.

以上接口是一些常用接口,但并不是全部接口。全部接口的介绍可以查看 message API 文档

# 2. 通过接口去读写对象

以下是两段样例代码:

#

#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;
}
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Nirvana 支付宝

支付宝