(原)ubuntu16中简单的使用google的protobuf

转载请注明出处:

http://www.cnblogs.com/darkknightzh/p/5804395.html

参考网址:

http://www.cnblogs.com/luosongchao/p/3969988.html

http://www.codeweblog.com/protocol-buffer%E5%AE%89%E8%A3%85%E5%8F%8A%E4%BD%BF%E7%94%A8-%E9%9D%9E%E5%B8%B8%E8%AF%A6%E7%BB%86/

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 }
View Code

说明:上面程序使用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.html160819更新

 170122更新结束

 ===========================================================================

5. 终端中输入./testAddBook,之后输入1,会存储pbinfo.log文件。

6. 终端中输入./testAddBook,之后输入2,显示如下:

说明解析的文件成功。

说明:对于optional可选项,可以不使用has_xxx()进行判断,此时不输出(程序有endl,所以会输出一个空行)(不知道其他使用方式时,会是什么情况)。

posted on 2016-08-24 19:59  darkknightzh  阅读(7762)  评论(2编辑  收藏  举报

导航