protobuf的应用

1.版本和引用

syntax = "proto3";    // proto2
package tutorial;     // package类似C++命名空间
// 可以引用本地的,也可以引用include里面的
import "google/protobuf/timestamp.proto";   // 已经写好的proto文件是可以引用

我们版本选择proto3  引用的是谷歌的protobuf包

2.如何编译

//protoc -I=/路径1 --cpp_out=./路径2 /路径1/addressbook.proto
//路径1为.proto所在的路径
//路径2为.cc和.h生成的位置
//将指定proto文件生成.pb.cc和.pb.h
//protoc -I=./ --cpp_out=./ addressbook.proto
//将对应目录的所有proto文件生成.pb.cc和.pb.h
//protoc -I=./ --cpp_out=./ *.proto

我们通过上述编译代码可以生成.pb.cc和.pb.h的文件 提供给我们c/c++开发语言使用使用

3.版本号选择

// [START java_declaration]
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
// [END java_declaration]

// [START csharp_declaration]
option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
// [END csharp_declaration]

我们可以选择java和C#的版本来使用protobuf包

4.主体内容

// 通讯录
// [START messages]  
message Person {    // message类似C++的class
  string name   = 1;  // 名字
  int32 id      = 2;  // Unique ID number for this person. 每个人的唯一id
  string email  = 3;

  enum PhoneType {    // enum 枚举类型
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;    // 字符串 电话号码
    PhoneType type = 2;   //
  }

  repeated PhoneNumber phones = 4;    // 重复0~多个,一个人有多个电话

  google.protobuf.Timestamp last_updated = 5; // import "google/protobuf/timestamp.proto"
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;   // 电话簿有多人的电话
}
// [END messages]

类似于C++创建类的方法

5.代码案例

// See README.txt for information and build instructions.

#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;


// 添加人联系
// 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;
    }
  }
  *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL)); // 设置时间
}
// 正确方式 g++ -std=c++11 -o add_person add_person.cc addressbook.pb.cc -lprotobuf  -lpthread
// 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.  address_book.add_people() 新建一个对象Person
  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;
}

6.结果展示

输入

输出