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

#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("alice@example.com");

    // 写入到文件
    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

#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("alice@example.com");
  person.add_email("alice.personal@gmail.com");

  // 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

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: alice@example.com

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

result ret: 0
Name: Alice
ID: 123
Is Active: 1
Email 1: alice@example.com
Email 2: alice.personal@gmail.com
Name: Alice
ID: 123
Is Active: 1
Email 1: alice@example.com
Email 2: alice.personal@gmail.com

3.其它实例

gitee 在线代码


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/571472.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【注解和反射】什么时候类会和不会被初始化?

继上一篇博客【注释和反射】类加载的过程-CSDN博客 目录 四、什么时候类会被初始化&#xff08;主动引用&#xff09;&#xff1f; 测试 五、什么情况下不会发生类的初始化&#xff08;被动引用&#xff09;&#xff1f; 测试 四、什么时候类会被初始化&#xff08;主动引用…

<网络> HTTP

目录 前言&#xff1a; 一、再谈协议 &#xff08;一&#xff09;认识URL &#xff08;二&#xff09;Encode 和 Decode 二、HTTP 协议 &#xff08;一&#xff09;协议格式 &#xff08;二&#xff09;见一见请求 &#xff08;三&#xff09;见一见响应 三、模拟实现响…

模块化 DeFi L2 “Mode” 整合 Covalent Network(CQT),以获 Web3 最大数据集的支持

Covalent Network&#xff08;CQT&#xff09;&#xff0c;作为 Web3 领先的数据层&#xff0c;宣布其统一 API 将与 Mode 集成&#xff0c;以加快其基于以太坊构建的专注于 DeFi 的模块化 Layer2 方案的数据访问速度。这一战略合作将通过为开发者提供更强大的工具和能力&#…

论文浅尝 | LoRA: 大模型的低秩适配

笔记整理&#xff1a;陈一林&#xff0c;东南大学硕士&#xff0c;研究方向为不确定知识图谱规则学习 链接&#xff1a;https://arxiv.org/abs/2106.09685 1、动机 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练&#xff0c;然后对特定任务或领域进行适应性…

`THREE.AudioAnalyser` 音频分析

demo案例 THREE.AudioAnalyser 音频分析 入参 (Input Parameters): audio: 一个 THREE.Audio 实例&#xff0c;代表要分析的音频。fftSize: 快速傅里叶变换&#xff08;FFT&#xff09;的大小&#xff0c;用于确定分析的精度和频率分辨率。smoothingTimeConstant: 平滑时间…

[lesson58]类模板的概念和意义

类模板的概念和意义 类模板 一些类主要用于存储和组织数据元素 类中数据组织的方式和数据元素的具体类型无关 如&#xff1a;数组类、链表类、Stack类、Queue类等 C中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。 C中的类模板…

如何通过cURL库实现远程控制插座

如何通过cURL库实现远程控制插座呢&#xff1f; 本文描述了使用cURL库调用HTTP接口&#xff0c;实现控制插座&#xff0c;即插即用&#xff0c;先插入插座&#xff0c;再接电器&#xff0c;实现远程控制。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格…

开源文本嵌入模型M3E

进入正文前&#xff0c;先扯点题外话 这两天遇到一个棘手的问题&#xff0c;在用 docker pull 拉取镜像时&#xff0c;会报错&#xff1a; x509: certificate has expired or is not yet valid 具体是下面&#x1f447;这样的 rootDS918:/volume2/docker/xiaoya# docker pul…

油猴脚本:bing 搜索结果居中

文章目录 效果预览脚本使用步骤安装油猴脚本添加脚本 效果预览 脚本 // UserScript // name bing居中 // namespace http://tampermonkey.net/ // version 2024-04-24 // description try to take over the world! // author You // match http…

牛客 题解

文章目录 day4_17**BC149** **简写单词**思路&#xff1a;模拟代码&#xff1a; dd爱框框思路&#xff1a;滑动窗口&#xff08;同向双指针&#xff09;代码&#xff1a; 除2&#xff01;思路&#xff1a;模拟贪心堆代码&#xff1a; day4_17 BC149 简写单词 https://www.now…

缓存神器-JetCache

序言 今天和大家聊聊阿里的一款缓存神器 JetCache。 一、缓存在开发实践中的问题 1.1 缓存方案的可扩展性问题 谈及缓存&#xff0c;其实有许多方案可供选择。例如&#xff1a;Guava Cache、Caffine、Encache、Redis 等。 这些缓存技术都能满足我们的需求&#xff0c;但现…

CPDA|0到1突破:构建高效数据分析体系的秘密武器

在现今信息爆炸的时代&#xff0c;数据已经渗透到了我们生活的方方面面&#xff0c;成为了决策、创新和竞争优势的关键。因此&#xff0c;构建一套高效的数据分析体系&#xff0c;对于企业和个人而言&#xff0c;都是至关重要的。那么&#xff0c;如何在众多的数据海洋中脱颖而…

自动化立体库安全使用管理制度

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到知识星球 【智能仓储物流技术研习社】自行下载 关于自动化立体库安…

Visual Studio导入libtorch(Cuda版)

Visual Studio导入libtorch&#xff08;Cuda版&#xff09; 一、安装 官网&#xff1a;https://pytorch.org/get-started/locally/ 相应地选择并下载 二、环境变量配置 解压zip&#xff0c;得到libtorch文件夹&#xff0c;将libtorch\lib和libtorch\bin对应路径添加到系统环…

如何把视频中的画面保存为图片?免费的工具不用白不用

在数字化时代&#xff0c;截取视频中的珍贵瞬间成为了人们创作、分享和保存回忆的重要方式。 那么&#xff0c;如何迅速捕捉视频中的精彩画面&#xff0c;留存美好瞬间呢&#xff1f;有人说直接截图就可以&#xff0c;如果直接截图就可以&#xff0c;小编就不用写这篇文章了&a…

Redis 安装及配置教程(Windows)【安装】

文章目录 一、简介一、 下载1. GitHub 下载2. 其它渠道 二、 安装1. ZIP2. MSI 软件 / 环境安装及配置目录 一、简介 Redis 官网地址&#xff1a;https://redis.io/   Redis 源码地址&#xff1a;https://github.com/redis/redis   Redis 官网安装地址&#xff08;无Windo…

组合预测 | Matlab实现LSTM-XGBoost长短期记忆网络组合极限梯度提升树多输入单输出回归预测

组合预测 | Matlab实现LSTM-XGBoost长短期记忆网络组合极限梯度提升树多输入单输出回归预测 目录 组合预测 | Matlab实现LSTM-XGBoost长短期记忆网络组合极限梯度提升树多输入单输出回归预测效果一览基本描述模型描述代码实现参考资料效果一览 基本描述 组合预测 | Matlab实现L…

AIGC-stable-diffusion(文本生成图片)+PaddleHub/HuggingFace

功能 stable-diffusion(文本生成图片)PaddleHub&#xff0c;HuggingFace两种调用方式 PaddleHub 环境 pip install paddlepaddle-gpu pip install paddlehub 代码 from PIL import Image import paddlehub as hub module hub.Module(namestable_diffusion)## 保存在demo…

Golang基础4-type、go测试

type相关 别名&#xff1a;本质上是更好的理解代码&#xff0c;比如byte(uint8)、rune(int32) 定义新类型&#xff0c;那么就相当于时struct了 package mainimport ("fmt""strconv" )// XInt 别名,在编译的时候会直接替换int type XInt int// YInt 自定…

C/C++程序设计实验报告4 | 函数实验

本文整理自博主本科大一《C/C程序设计》专业课的课内实验报告&#xff0c;适合C语言初学者们学习、练习。 编译器&#xff1a;gcc 10.3.0 ---- 注&#xff1a; 1.虽然课程名为C程序设计&#xff0c;但实际上当时校内该课的内容大部分其实都是C语言&#xff0c;C的元素最多可能只…
最新文章