07_c/c++开源库protobuf序列化

1.简介与安装

简介: 无, 懂的都懂

安装

sudo apt install protobuf-compiler protobuf-c-compiler libprotobuf-dev

编译依赖

pkg-config --cflags --libs protobuf

-pthread -lprotobuf -pthread

编译选项: -pthread

链接选项: -lprotobuf -pthread

2.实例

1.代码

实例1

addressbook.proto

复制代码
syntax = "proto3";

package tutorial;

message Person {
  string name = 1;
  string email = 2;
}

message AddressBook {
  repeated Person people = 1;
}

1_addressbook_protobuf实例.cc

c++ 复制代码
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"

void WriteAddressBook()
{
    tutorial::AddressBook address_book;

    // 添加一个 Person
    tutorial::Person *person = address_book.add_people();
    person->set_name("Alice");
    person->set_email("[email protected]");

    // 写入到文件
    std::ofstream output("addressbook.data", std::ios::binary);
    if (!address_book.SerializeToOstream(&output))
    {
        std::cerr << "Failed to write address book." << std::endl;
        return;
    }
}

void ReadAddressBook()
{
    tutorial::AddressBook address_book;

    // 从文件读取
    std::ifstream input("addressbook.data", std::ios::binary);
    if (!address_book.ParseFromIstream(&input))
    {
        std::cerr << "Failed to read address book." << std::endl;
        return;
    }

    // 输出读取到的人名
    for (int i = 0; i < address_book.people_size(); ++i)
    {
        const tutorial::Person &person = address_book.people(i);
        std::cout << "Name: " << person.name() << ", Email: " << person.email() << std::endl;
    }
}

int main()
{
    WriteAddressBook();
    ReadAddressBook();
    return 0;
}
实例2

person.proto

复制代码
syntax = "proto3";  // 使用Protocol Buffers v3语法

package example;  // 定义包名,便于组织和避免命名冲突

message Person {  // 定义名为Person的消息类型
  string name = 1;  // 字符串类型字段,标签为1
  int32 id = 2;    // 整型字段,标签为2
  bool is_active = 3;  // 布尔型字段,标签为3
  repeated string email = 4;  // 重复字段,表示字符串列表,标签为4
}

2_protobuf_person_序列号到字节.cc

c++ 复制代码
#include "person.pb.h"
#include <fstream>
#include <iostream>
#include <stdint.h>
#include <vector>
using namespace std;

// 写入文件
void WriteToFile(const std::string& filename, const example::Person& person) {
  std::fstream output(filename, std::ios::out | std::ios::trunc | std::ios::binary);
  if (!person.SerializeToOstream(&output)) {
    std::cerr << "Failed to write person." << std::endl;
  }
}

// 从文件读取
void ReadFromFile(const std::string& filename, example::Person& person) {
  std::fstream input(filename, std::ios::in | std::ios::binary);
  if (!person.ParseFromIstream(&input)) {
    std::cerr << "Failed to parse person." << std::endl;
  }
}

// 打印反序列化后的数据
void PrintPerson(const example::Person& person) {
  std::cout << "Name: " << person.name() << std::endl;
  std::cout << "ID: " << person.id() << std::endl;
  std::cout << "Is Active: " << person.is_active() << std::endl;
  // 打印反序列化后的数据
  for (int i = 0; i < person.email_size(); ++i) {
    std::cout << "Email " << i + 1 << ": " << person.email(i) << std::endl;
  }
}

int main() {
  // 创建并填充一个Person对象
  example::Person person;
  person.set_name("Alice");
  person.set_id(123);
  person.set_is_active(true);
  person.add_email("[email protected]");
  person.add_email("[email protected]");

  // 1.序列化到 字节
  uint8_t buf[256] = { 0 };
  bool ret = person.SerializeToArray(buf, sizeof(buf));

  // 2.反序列化从 字节
  example::Person new_person;
  ret = new_person.ParseFromArray(buf, sizeof(buf));

  cout << "result ret: " << ret << endl;
  PrintPerson(new_person);

  // 3.读写probuf测试
  WriteToFile("person.bin", person);  // 写入文件
  ReadFromFile("person.bin", new_person); // 从文件读取
  PrintPerson(new_person);            // 打印反序列化后的数据

  return 0;
}

2.scons编译

SConstruct

python 复制代码
import os
## 模板2
env = Environment()
env["PROGSUFFIX"] = ".out"            # 可执行后缀.out
env["CCFLAGS"] = " -g3 -O0 -Wall"       # gdb 调试开关
# -pthread -lprotobuf
env.MergeFlags(["!pkg-config protobuf --cflags --libs"])

def build_protobuf(file_path):
    file,file_ext = os.path.splitext(file_path)
    print(file,file_ext)
    if file_ext != ".proto":
        raise f"{file_path} not .proto file"
    cmd=f"protoc --cpp_out=. {file}.proto"
    Command(f"{file}.pb.h",file_path,cmd)

build_protobuf("addressbook.proto")
env.Program(Split("1_addressbook_protobuf实例.cc addressbook.pb.cc"))
build_protobuf("person.proto")
env.Program(Split("2_protobuf_person_序列号到字节.cc person.pb.cc"))

注意:

protobuf编译方法
protoc --cpp_out=. addressbook.proto

生成 addressbook.pb.cc addressbook.pb.h

scons中并没有直接构建protobuf方法, 可以使用scons Command(target_file, src_file, cmd)

Command使用说明: 如果src_file 时间戳比 target_file 新, 则执行cmd命令

示例: Command("addressbook.pb.h", "addressbook.proto", "rotoc --cpp_out=. addressbook.proto")


scons

scons: Reading SConscript files ...

addressbook .proto

person .proto

scons: done reading SConscript files.

scons: Building targets ...

protoc --cpp_out=. addressbook.proto

g++ -o 1_addressbook_protobuf实例.o -c -g3 -O0 -Wall -pthread 1_addressbook_protobuf实例.cc

g++ -o addressbook.pb.o -c -g3 -O0 -Wall -pthread addressbook.pb.cc

g++ -o 1_addressbook_protobuf实例.out -pthread 1_addressbook_protobuf实例.o addressbook.pb.o -lprotobuf

protoc --cpp_out=. person.proto

g++ -o 2_protobuf_person_序列号到字节.o -c -g3 -O0 -Wall -pthread 2_protobuf_person_序列号到字节.cc

g++ -o person.pb.o -c -g3 -O0 -Wall -pthread person.pb.cc

g++ -o 2_protobuf_person_序列号到字节.out -pthread 2_protobuf_person_序列号到字节.o person.pb.o -lprotobuf

scons: done building targets.

3.验证测试

./1_addressbook_protobuf实例.out

Name: Alice, Email: [email protected]

./2_protobuf_person_序列号到字节.out

result ret: 0

Name: Alice

ID: 123

Is Active: 1

Email 1: [email protected]

Email 2: [email protected]

Name: Alice

ID: 123

Is Active: 1

Email 1: [email protected]

Email 2: [email protected]

3.其它实例

gitee 在线代码


相关推荐
freyazzr7 分钟前
C++八股 | Day2 | atom/函数指针/指针函数/struct、Class/静态局部变量、局部变量、全局变量/强制类型转换
c++
fpcc1 小时前
跟我学c++中级篇——理解类型推导和C++不同版本的支持
开发语言·c++
终焉代码2 小时前
STL解析——list的使用
开发语言·c++
说私域2 小时前
定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究
人工智能·小程序·开源·零售
DevangLic2 小时前
【 *p取出内容 &a得到地址】
c++
鑫鑫向栄2 小时前
[蓝桥杯]修改数组
数据结构·c++·算法·蓝桥杯·动态规划
鑫鑫向栄2 小时前
[蓝桥杯]带分数
数据结构·c++·算法·职场和发展·蓝桥杯
m0_552200823 小时前
《UE5_C++多人TPS完整教程》学习笔记37 ——《P38 变量复制(Variable Replication)》
c++·游戏·ue5
小wanga3 小时前
【递归、搜索与回溯】专题三 穷举vs暴搜vs回溯vs剪枝
c++·算法·机器学习·剪枝
Code_流苏4 小时前
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
开发语言·c++·stl容器·课设·期末大作业·日历程序·面向对象设计