天天看点

2022-02-18 编译并使用protobuf完成c++序列化

目录

​​摘要:​​

​​编译protobuf:​​

​​protobuf地址:​​

​​编译:​​

​​使用protobuf:​​

​​使用protoc生成c++协议文件:​​

​​测试proto的代码:​​

摘要:

记录编译并使用protobuf完成c++序列化

编译protobuf:

protobuf地址:

​​https://github.com/protocolbuffers/protobuf/releases​​

备份地址:

​​protobuf-all-3.19.4.tar.gz-互联网文档类资源-​​

编译:

tar -xzvf protobuf-all-3.19.4.tar.gz

cd protobuf-3.19.4/


./configure

make all

make install      

默认安装的protobuf库的位置:

/usr/local/lib      

编译时依赖protobuf库

-L/usr/local/lib -lprotobuf      
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH      

使用protobuf:

.
├── agent
├── build.sh
├── Makefile
├── run_proto.sh
├── src
│   ├── base
│   ├── config
│   ├── http
│   │   └── httplib.h
│   ├── proc
│   ├── proto
│   │   ├── hello.pb.cc
│   │   ├── hello.pb.h
│   │   └── hello.proto
│   ├── router
│   │   ├── router.cc
│   │   ├── router.h
│   │   ├── router_test.cc
│   │   └── router_test.h
│   └── server
│       ├── run.cc
│       └── server.h
└── utest
    └── ut_testData.sh

9 directories, 15 files      
syntax = "proto2";

message helloworld   
{
    required int32         id=1;   
    optional string        str=2;  
    enum PhoneType {               
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
      }
    message PhoneNumber {         
        optional string number = 1;
        optional PhoneType type = 2;
      }
    repeated PhoneNumber phones = 4;
}
      

使用protoc生成c++协议文件:

protoc --cpp_out=. ./src/proto/hello.proto      
  • --cpp_out: 生成的cpp文件位置, 相对于后边跟随的proto位置
  • 后边跟随指定的proto文件

测试proto的代码:

#include <iostream>

#include "../src/proto/hello.pb.h"


bool writeBuf(string file_path)
{
    helloworld msg1;   // 包名::Message名 
    helloworld::PhoneNumber *phone;  // 注意嵌套Message使用指针
    msg1.set_id(100);
    msg1.set_str("200");

    phone = msg1.add_phones();
    phone->set_number("12345");
    phone->set_type(helloworld_PhoneType_HOME);  // 注意Enum的调用方式(所有的默认值相当于C++中的Const对象, 所以直接使用类调用)

    // Write the new address book back to disk. 
    fstream output(file_path, ios::out | ios::trunc | ios::binary); 

    if (!msg1.SerializeToOstream(&output)) { 
        std::cerr << "Failed to write msg." << std::endl; 
        return false; 
    }     
    return true;
}

// 输出数据
void ListMsg(const helloworld & msg) { 
    cout << msg.id() << std::endl; 
    cout << msg.str() << std::endl; 
    for (int i =0; i<msg.phones_size(); i++)
    {
        // 注意此时调用嵌套类中的值不是用的指针方式.
        cout << msg.phones(i).number() << std::endl;
    }
} 

// 读取文件,写入到protobuf生成的类中
bool readBuf(string file_path)
{
    helloworld msg1;
    { 
        fstream input(file_path, ios::in | ios::binary); 
        if (!msg1.ParseFromIstream(&input)) { 
            std::cerr << "Failed to parse address book." << std::endl; 
            return -1; 
        } 
    } 
    ListMsg(msg1); 
}

int main()  
{  
    string path = "../test.log";
    writeBuf(path);
    readBuf(path);
    return 0;  
}  

      
root@localhost:~/work/ndb-influxdb-instance/src/agent# ldd agent 
  linux-vdso.so.1 (0x00007ffe49789000)
  libprotobuf.so.30 => /usr/local/lib/libprotobuf.so.30 (0x00007f230780a000)
  libz.so.1 => /lib64/libz.so.1 (0x00007f23075f3000)
  libbrotlicommon.so.1 => /lib64/libbrotlicommon.so.1 (0x00007f23073d2000)
  libbrotlienc.so.1 => /lib64/libbrotlienc.so.1 (0x00007f2307146000)
  libbrotlidec.so.1 => /lib64/libbrotlidec.so.1 (0x00007f2306f39000)
  libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f2306ba4000)
  libm.so.6 => /lib64/libm.so.6 (0x00007f2306822000)
  libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f230660a000)
  libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f23063ea000)
  libc.so.6 => /lib64/libc.so.6 (0x00007f2306025000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f2307cb0000)