(原)ubuntu16中简单的使用google的protobuf
转载请注明出处:
http://www.cnblogs.com/darkknightzh/p/5804395.html
参考网址:
http://www.cnblogs.com/luosongchao/p/3969988.html
1. 在当前文件夹内新建addressbook.proto,并输入:
package ContactInfo; message Person { required string curName = 1; required int32 curId = 2; optional string curEmail = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 4; optional PhoneType type = 2[default = HOME]; } repeated PhoneNumber phone = 4; } message AddressBook { required string owner = 10; repeated Person personInfo = 6; }
2. 将终端定位到当前文件夹,并输入:
protoc --cpp_out=./ addressbook.proto
说明:a 如果希望生成的.h和.cpp都在当前文件夹,则--cpp_out=./即可。
b 如果使用如下命令:
protoc -I=src --cpp_out=dst src/ addressbook.proto
则addressbook.proto在当前文件夹的src文件夹里,生成的.h和.cpp均位于当前文件夹下的dst文件夹下面。
c 生成的头文件中,ContactInfo为命名空间,里面包含Person、PhoneNumber、AddressBook三个类。枚举类型则看该类型所在的类,使用作用域限定符来访问,如:
ContactInfo::Person::MOBILE
3. 在生成的.h和.cpp文件所在的文件夹内,新建testAddBook.cpp,并输入:
1 #include "addressbook.pb.h" 2 #include <fstream> 3 #include <iostream> 4 using namespace std; 5 6 ///////////////////////////////////////////////////////////////////////////////// 7 int saveAddInfo() 8 { 9 ContactInfo::AddressBook addbook; 10 addbook.set_owner("xxx"); 11 12 // first person 13 ContactInfo::Person* pperson = addbook.add_personinfo(); 14 pperson->set_curname("aaa"); 15 pperson->set_curid(25); 16 pperson->set_curemail("aaa@126.com"); 17 18 ContactInfo::Person_PhoneNumber* pPhoneNum = pperson->add_phone(); 19 pPhoneNum->set_number("111111111"); 20 pPhoneNum->set_type(ContactInfo::Person::HOME); 21 22 pPhoneNum = pperson->add_phone(); 23 pPhoneNum->set_number("222222222"); 24 pPhoneNum->set_type(ContactInfo::Person::MOBILE); 25 26 // second person 27 pperson = addbook.add_personinfo(); 28 pperson->set_curname("bbb"); 29 pperson->set_curid(30); 30 // pperson->set_curemail("bbb@126.com"); 31 32 pPhoneNum = pperson->add_phone(); 33 pPhoneNum->set_number("333333333"); 34 // pPhoneNum->set_type(ContactInfo::Person::HOME); 35 36 pPhoneNum = pperson->add_phone(); 37 pPhoneNum->set_number("444444444"); 38 pPhoneNum->set_type(ContactInfo::Person::MOBILE); 39 40 // int length = addbook.ByteSize(); 41 // char* buf = new char[length]; // serialize to char*, and transmit by net or others 42 // addbook.SerializeToArray(buf,length); 43 44 fstream output("pbinfo.log", ios::out|ios::trunc|ios::binary); 45 if(!addbook.SerializeToOstream(&output)) 46 { 47 cerr << "fail to write msg" << endl; 48 //delete[] buf; 49 return -1; 50 } 51 52 //delete[] buf; 53 return 0; 54 } 55 56 //////////////////////////////////////////////////////////////////////////// 57 void showMsg(const ContactInfo::AddressBook& addbook) 58 { 59 cout << addbook.owner() << endl; 60 for (int i = 0; i < addbook.personinfo_size(); ++i) 61 { 62 cout << addbook.personinfo(i).curname() << endl; 63 cout << addbook.personinfo(i).curid() << endl; 64 if(addbook.personinfo(i).has_curemail()) 65 cout << addbook.personinfo(i).curemail() << endl; 66 else 67 cout << "no email" << endl; 68 69 for (int j = 0; j < addbook.personinfo(i).phone_size(); ++j) 70 { 71 cout<<addbook.personinfo(i).phone(j).number() << endl; 72 if(addbook.personinfo(i).phone(j).has_type()) 73 cout << addbook.personinfo(i).phone(j).type() << endl; 74 else 75 cout << "no phone type" << endl; 76 } 77 } 78 } 79 80 void showMsgbyAuto(ContactInfo::AddressBook addbook) 81 { 82 cout << addbook.owner() << endl; 83 84 auto pperson = addbook.mutable_personinfo(); 85 for (auto it = pperson->begin(); it != pperson->end(); ++it) 86 { 87 cout << it->curname() << endl; 88 cout << it->curid() << endl; 89 if(it->has_curemail()) 90 cout << it->curemail() << endl; 91 else 92 cout << "no email" << endl; 93 94 auto pPhoneNum = it->mutable_phone(); 95 for (auto ij = pPhoneNum->begin(); ij != pPhoneNum->end(); ++ij) 96 { 97 cout << ij->number() << endl; 98 if(ij->has_type()) 99 cout << ij->type() << endl; 100 else 101 cout << "no phone type" << endl; 102 } 103 } 104 } 105 106 int loadAddInfo() 107 { 108 ContactInfo::AddressBook addbook; 109 110 fstream input("pbinfo.log", ios::in|ios::binary); 111 if(!addbook.ParseFromIstream(&input)) 112 { 113 cout << "fail to write msg" << endl; 114 return -1; 115 } 116 cout << "now show msg" << endl; 117 showMsg(addbook); 118 cout << endl; 119 showMsgbyAuto(addbook); 120 121 return 0; 122 } 123 124 /////////////////////////////////////////////////////////////////////////////// 125 int main() 126 { 127 int choice; 128 cout << "input choice: 1 for save, 2 for load" << endl; 129 cin >> choice; 130 if(1 == choice) 131 { 132 saveAddInfo(); 133 } 134 else if (2 == choice) 135 { 136 loadAddInfo(); 137 } 138 139 return 0; 140 }
说明:上面程序使用SerializeToArray后,可以将数据放到buf的缓冲区中,方便使用网络或者其他方式发送。
4. 终端定位到testAddBook.cpp所在文件夹,并输入:
g++ -std=c++11 addressbook.pb.cc testAddBook.cpp -o testAddBook -lprotobuf -pthread
说明:a 上面程序showMsgbyAuto函数使用了C++11特性,因而终端中需要加上-std=c++11;否则可以不加。如果不使用C++11特性,则使用下面的方式访问,但是太长。。。:
::google::protobuf::RepeatedPtrField< ::ContactInfo::Person >
b 如果protobuf没有安装到/usr路径,而是/usr/local路径,可能需要下面的命令:
c 此处不能使用gcc编译,我这里提示出错了:
/usr/bin/ld: /tmp/ccO3HeHo.o: undefined reference to symbol '_ZNSaIcED1Ev@@GLIBCXX_3.4' //usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status
===========================================================================
170122更新:
d 如果编译该cpp文件的时候,提示好多未定义的引用:
addressbook.pb.cc:(.text+0x133):对‘google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(google::protobuf::Descriptor const*, google::protobuf::Message const*, int const*, int, int, int, int, int, int)’未定义的引用 addressbook.pb.cc:(.text+0x193):对‘google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(google::protobuf::Descriptor const*, google::protobuf::Message const*, int const*, int, int, int, int, int, int)’未定义的引用
可能是因为电脑安装了两个不同版本的protobuf(ubuntu16默认已经安装了protobuf.so.9这系列的,新装的是protobuf.so.10系列的)。默认的路径见http://www.cnblogs.com/darkknightzh/p/5782992.html中160819更新。
170122更新结束
===========================================================================
5. 终端中输入./testAddBook,之后输入1,会存储pbinfo.log文件。
6. 终端中输入./testAddBook,之后输入2,显示如下:
说明解析的文件成功。
说明:对于optional可选项,可以不使用has_xxx()进行判断,此时不输出(程序有endl,所以会输出一个空行)(不知道其他使用方式时,会是什么情况)。
posted on 2016-08-24 19:59 darkknightzh 阅读(7778) 评论(2) 编辑 收藏 举报