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

本文档详细介绍了如何从源码编译protobuf,然后在C++项目中使用protobuf进行序列化操作。首先,从github下载protobuf源码并进行编译安装。接着,通过protoc工具生成C++代码,并在测试程序中展示了如何创建、序列化和反序列化protobuf消息。文章还附带了一个简单的proto文件和对应的C++测试代码作为示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

摘要:

编译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

hello.proto:

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值