安裝(Ubuntu 16.04)
- sudo apt-get install autoconf automake libtool curl make g++ unzip
- git clone https://github.com/google/protobuf.git
- cd protobuf
- git submodule update --init --recursive
- ./autogen.sh
- ./configure
- make
- make check
- sudo make install
- sudo ldconfig # refresh shared library cache
- protoc --version
如果能查看proto的版本,則代表安裝成功,否則失敗。
簡介
本文主要介紹proto3的使用以及個人理解。關於proto版本的不同以及深入理解,可以參考下面鏈接。
proto2
proto3
用法
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("fun@qq.com");
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("main@qq.com");
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 :main@qq.com
main phone :2119
main phone type :2
AddBook id :1111
AddBook name :fun_name
AddBook email :fun@qq.com
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/