C++ProtoBuf的安装与使用

安装(Ubuntu 16.04)

  1. sudo apt-get install autoconf automake libtool curl make g++ unzip
  2. git clone https://github.com/google/protobuf.git
  3. cd protobuf
  4. git submodule update --init --recursive
  5. ./autogen.sh
  6. ./configure
  7. make
  8. make check
  9. sudo make install
  10. sudo ldconfig # refresh shared library cache
  11. protoc --version

如果能查看proto的版本,则代表安装成功,否则失败。

简介

本文主要介绍proto3的使用以及个人理解。关于proto版本的不同以及深入理解,可以参考下面链接。

https://www.jianshu.com/p/5e65f33c4b15?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation    //数据传输格式

proto2

https://www.jianshu.com/p/e89594ecc1db

proto3

https://blog.csdn.net/u011518120/article/details/54604615

用法

proto3

/*****PbTest.proto******/

syntax = "proto3";

package tutorial;

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
   Person people = 1;
}
protoc --cpp_out=. PbTest.proto //先编译proto文件生成.cc和.h文件

若对proto文件进行修改,则需要重新使用protoc进行编译,生成新的cc和h文件。

#include <iostream>
#include "PbTest.pb.h"

void BookAdd(tutorial::Person *person)
{
  person->set_email("[email protected]");
  person->set_name("fun_name");
  person->set_id(1111);
  tutorial::Person::PhoneNumber *phone_num=person->add_phones();
  phone_num->set_number("1999");
}

int main() {
  tutorial::Person test;
  test.set_id(2111);
  test.set_name("main_name");
  test.set_email("[email protected]");

  tutorial::Person::PhoneNumber phone_num;
  phone_num.set_number("2119");
  phone_num.set_type(tutorial::Person::WORK);

//  tutorial::Person_PhoneNumber phone;    //等价上面的phone_num
//  phone.set_number("2119");
//  phone.set_type(tutorial::Person_PhoneType::Person_PhoneType_HOME);
//  std::cout<<phone.number()<<std::endl;
//  std::cout<<phone.type()<<std::endl;

  tutorial::AddressBook book;
  BookAdd(book.mutable_people());
//  book.mutable_people()->set_name("main2test");    //与BookAdd函数调用等价

  std::cout<<"main id :"<<test.id()<<std::endl;
  std::cout<<"main name :"<<test.name()<<std::endl;
  std::cout<<"main email :"<<test.email()<<std::endl;
  std::cout<<"main phone :"<<phone_num.number()<<std::endl;
  std::cout<<"main phone type :"<<phone_num.type()<<std::endl;

  const tutorial::Person &person=book.people();
  std::cout<<"AddBook id :"<<person.id()<<std::endl;
  std::cout<<"AddBook name :"<<person.name()<<std::endl;
  std::cout<<"AddBook email :"<<person.email()<<std::endl;
  const tutorial::Person::PhoneNumber &num_phone=person.phones(0);
  std::cout<<"AddBook phone :"<<num_phone.number()<<std::endl;
  std::cout<<"AddBook phone type:"<<num_phone.type()<<std::endl;
  return 0;
}
g++ main.cc PbTest.pb.cc  -lprotobuf -lpthread

输出结果

main id :2111
main name :main_name
main email :[email protected]
main phone :2119
main phone type :2
AddBook id :1111
AddBook name :fun_name
AddBook email :[email protected]
AddBook phone :1999
AddBook phone type:0

总结

    关于proto3的使用过程中,与proto2比较起来,3去掉了字段的限制,以及默认值。虽然说3去掉了[default=value]的操作,但是3在枚举类型中,必须要从0开始,并且枚举的默认值也为0。对于bool类型,默认是false。正因为由于3有了默认值的操作,所以在判断是用户赋予的值还是默认值,则需要话费一些功夫去判断。(由于本人不常用,有需要者,可以百度。)
    如果需要使用oneof字段时,它的原理有点类似与共享(union)结构体。如果数据结构复杂的话,也可以采用c++中的map来存储key-value结构。value也可以是proto中的message类型。
    踩坑:如果字段前面有repeated修饰的话,对其进行修改的时候则需要通过proto对象中的add_()方法对内部嵌套的字段进行赋值。若没有的话,则可以采用 obj.mutable_()->set_()来进行赋值。

若需要参考proto2代码,则可以参考:
https://github.com/protobuf-c/protobuf-c/wiki/Examples
https://github.com/SmallBlackEgg/proto/

猜你喜欢

转载自www.cnblogs.com/SmallBlackEgg/p/11628932.html