zoukankan      html  css  js  c++  java
  • (原)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,所以会输出一个空行)(不知道其他使用方式时,会是什么情况)。

  • 相关阅读:
    通过WebService跨平台上传大文件到服务器
    C# 委托、Lambda表达式和事件——学习总结
    WIN8、WIN7访问Windows Server 2003服务器的数据库速度很慢、远程速度很慢的解决方法
    C#中接口与抽象类的区别
    DataGridView重查后,返回原来所在行
    需要开拓的领域
    FTP使用心得
    VS的几个实用快捷键
    C#中窗体、MDI的使用心得
    水晶报表使用心得
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/5804395.html
Copyright © 2011-2022 走看看