google protocol学习总结

安装protocol 

sudo apt-get install libprotobuf-dev protobuf-compiler 

ubuntu16.04 因为之前安装过ros 所以系统中有默认的 protobuf ,至于使用哪个版本的protocol,可以自己设置,参考

Ubuntu卸载并重新安装protocol

安装完成 protoc –version 

libprotoc 2.6.1

which protoc 可以查看 protoc的安装路径

protocol是一个完全抽象的数据存储和读取的包,独立于操作系统,独立于语言。所以不论是linux还是win,不论是c++ python c# java R GO 都可以使用。

其储存形式是二进制文件,所以相比于xml,对于相同的数据,能节约3-10倍空间,存储和读取效率高20-100倍。

举个例子:

数据源

xml

  <person>
    <name>John Doe</name>
    <email>[email protected]</email>
  </person>

protocol

扫描二维码关注公众号,回复: 4301307 查看本文章
# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
  name: "John Doe"
  email: "[email protected]"
}

输出

xml

  cout << "Name: "
       << person.getElementsByTagName("name")->item(0)->innerText()
       << endl;
  cout << "E-mail: "
       << person.getElementsByTagName("email")->item(0)->innerText()
       << endl;

protocol

  cout << "Name: " << person.name() << endl;
  cout << "E-mail: " << person.email() << endl;

下面是对tutorial的一些搬运:

最重要的三点:

  • Define message formats in a .proto file.
  • Use the protocol buffer compiler.
  • Use the C++ protocol buffer API to write and read messages. 

文件是.proto形式,就像上面看到的那样

.proto形式的文件还不能直接使用,因为这个是抽象的,独立于平台和语言,所以有一个编译器,自动把.proto文件翻译成平台下你要的语言,我这里是cpp。

直接调用编译器生成的.cc和.h文件,压根不用关心内怎么实现的,反正编译器帮你做好了,你要做的就是调用API。

首先在空文件夹中新建一个addressbook.proto

内容如下
 

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 phone = 4;
}
 
message AddressBook {
  repeated Person person = 1;
}

原始数据类型可以是boolint32floatdouble, andstring

其他数据类型也可以一级一级包含,在代码中已经很明确了。

package tutorial;

意思是命名空间namespace
required声明的变量是必须被初始化的,如果没有初始化,在debug模式下会报错。

optional声明的变量是可以选择性初始化。

repeated声明的变量是可以重复添加的。

注意一些=1 =2 =3,是一种寻址机制,1-15在生成的bin中,可以快速的被读取和写入,所以重复使用的数据尽量放在1-15号。

下面就是编译了,注意这儿的编译只是将.proto文件翻译成我们要的文件,并不是生成什么可执行程序。
 

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

我的是

protoc -I=./ --cpp_out=./ ./addressbook.proto

之后会生成两个文件分别是addressbook.pb.h addressbook.pb.cc

这里不在贴出具体生成代码.

之后就是调用API了

Standard Message Methods
Each message class also contains a number of other methods that let you check or manipulate the entire message, including:

  • bool IsInitialized() const;: checks if all the required fields have been set.
  • string DebugString() const;: returns a human-readable representation of the message, particularly useful for debugging.
  • void CopyFrom(const Person& from);: overwrites the message with the given message's values.
  • void Clear();: clears all the elements back to the empty state.

These and the I/O methods described in the following section implement the Message interface shared by all C++ protocol buffer classes. For more info, see thecomplete API documentation for Message.        


Parsing and Serialization
Finally, each protocol buffer class has methods for writing and reading messages of your chosen type using the protocol bufferbinary format. These include:

  • bool SerializeToString(string* output) const;: serializes the message and stores the bytes in the given string. Note that the bytes are binary, not text; we only use thestring class as a convenient container.
  • bool ParseFromString(const string& data);: parses a message from the given string.
  • 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.

These are just a couple of the options provided for parsing and serialization. Again, see theMessage API reference for a complete list.       


最后就是写一个测试代码了。

新建一个test1.cpp

#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_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;
    }
  }
}
 
// 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_person());
 
  {
    // 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;
}


代码其实就是新建了一个联系人,里面可以放许多联系人,电话,email。

然后这样子编译。好像使用aptget install并不能让g++自动找到.so文件。所以手动设置路径。

g++ test1.cpp addressbook.pb.cc -L /usr/lib/x86_64-linux-gnu -l protobuf -o test1

运行以后会生成一个二进制文件。这个文件也是protocol的最终产物了。一个写入和加载速度最快,体积最小的东西。

下面一段程序是读取这个文件的内容。

#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.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;
    }
 
    for (int j = 0; 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;
 
  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;
}

参考链接:

https://blog.csdn.net/u010566411/article/details/52841460 

猜你喜欢

转载自blog.csdn.net/p942005405/article/details/84530833