嵌入式Protobuf扫盲入门

本文介绍了Google的Protocol Buffer(Protobuf)库,包括其历史、序列化概念和在不同语言中的支持。重点讲解了在嵌入式环境中,特别是STM32微控制器上使用Nanopb库进行Protobuf序列化和反序列化的步骤,包括.proto文件的编写、编译和代码移植。此外,还提到了Proto2和Proto3的语法差异,并强调了两者不能混用。
摘要由CSDN通过智能技术生成

嵌入式Protobuf扫盲入门

什么是Protobuf

Protocol Buffer (简称Protobuf) 是Google出品的性能优异、跨语言、跨平台的序列化库。

2001年初,Protobuf首先在Google内部创建, 我们把它称之为 proto1,一直以来在Google的内部使用,其中也不断的演化,根据使用者的需求也添加很多新的功能,一些内部库依赖它。几乎每个Google的开发者都会使用到它。

Google开始开源它的内部项目时,因为依赖的关系,所以他们决定首先把Protobuf开源出去。 proto1在演化的过程中有些混乱,所以Protobuf的开发者重写了Protobuf的实现,保留了proto1的大部分设计,以及proto1的很多的想法。但是开源的proto2不依赖任何的Google的库,代码也相当的清晰。2008年7月7日,Protobuf开始公布出来。

Protobuf公布出来也得到了大家的广泛的关注, 逐步地也得到了大家的认可,很多项目也采用Protobuf进行消息的通讯,还有基于Protobuf的微服务框架GRPC。在使用的过程中,大家也提出了很多的意见和建议,Protobuf也在演化,于2016年推出了Proto3。 Proto3简化了proto2的开发,提高了开发的效能,但是也带来了版本不兼容的问题。

目前Protobuf的稳定版本是3.9.2,于2019年9月23日发布。由于很多公司很早的就采用了Protobuf,所以很多项目还在使用proto2协议,目前是proto2和proto3同时在使用的状态。

Protocol Buffer名称来自于初期一个主要的类的名称ProtocolBuffer。

Google当前并没有Protobuf的相关专利,所以不必担心侵权的问题。

序列化

序列化(serialization、marshalling)的过程是指将数据结构或者对象的状态转换成可以存储(比如文件、内存)或者传输的格式(比如网络)。反向操作就是反序列化(deserialization、unmarshalling)的过程。

Protobuf支持很多语言,比如C++、C#、Dart、Go、Java、Python、Rust等,同时也是跨平台的,所以得到了广泛的应用。

Protobuf包含序列化格式的定义、各种语言的库以及一个IDL编译器。正常情况下你需要定义proto文件,然后使用IDL编译器编译成你需要的语言。

鉴于官方推荐新代码采用proto3,这个教程主要介绍proto3的开发。官方建议新项目采用proto3,老项目因为兼容性的问题继续使用proto2,并且会长时间的支持proto2

嵌入式的Protobuf

很遗憾,谷歌官方并没有支持的Protobuf c官方库,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r9IPrUJY-1630647326215)(20210903102239.png)]

但是在其网页介绍的第三方附加组件中包含了Protobuf c工具实现,Protocol Buffers 的第三方附加组件其中支持c实现的有以下

C: https://github.com/protobuf-c/protobuf-c
C: http://koti.kapsi.fi/jpa/nanopb/
C: https://github.com/cloudwu/pbc/
C: https://github.com/haberman/upb/wiki
C: https://github.com/squidfunk/protobluff
C: https://github.com/eerimoq/pbtools

嵌入式运用比较广泛的是Nanopb,接下来就手把手使用Nanopd 序列化数据移植到STM32工程中。

下载Nanopb工具

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L210ahd7-1630647326217)(2.png)]

这里选择windows版本

在这里插入图片描述

解压后的文件夹内容如下:

在这里插入图片描述

将\nanopb-0.4.5-windows-x86\generator-bin路径添加到系统环境,(我的电脑->右键属性->高级系统设置->高级->环境变量)

在这里插入图片描述

接着准备一个STM串口打印的工程,在工程下创建protobuff文件夹,

在这里插入图片描述

将\nanopb-0.4.5-windows-x86\以下七个文件复制到protobuff文件夹下

在这里插入图片描述

接着创建一个student.proto文件,注意后缀为.proto

syntax = "proto2";

message Student
{
 required uint32 num      = 1;
 required uint32 py_score = 2;
 required uint32 c_score  = 3;
}

然后在工程中创建的protobuff文件夹中,按住Shift+鼠标右键,选中在此处打开Powershell窗口,(或者win+r 输入cmd 进入到工程中的protobuff文件夹中),在窗口输入

protoc --nanopb_out=. student.proto

在这里插入图片描述

此时在文件夹下生成了student.pb.c和student.pb.h文件

请添加图片描述

将protobuff文件夹中的源码和头文件添加到工程中,

请添加图片描述

接着添加测试代码:

#include "student.pb.h"
#include <pb_encode.h>
#include <pb_decode.h>

void protobuf_test(void)
{
  uint8_t buffer[64] = {0}; //需要发送的数据缓存
  Student pack_stu = {0};	//需要编码的序列化的对象
  pb_ostream_t o_stream = {0}; //初始化输出序列化对象
  Student unpack_stu = {0};	//初始化输出序列化对象
  pb_istream_t i_stream = {0}; //初始化接收序列化对象

  // 组包
  pack_stu.num  = 88;
  pack_stu.py_score = 90;
  pack_stu.c_score = 99;
  o_stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
  pb_encode(&o_stream, Student_fields, &pack_stu);

  // 解包
  i_stream = pb_istream_from_buffer(buffer, sizeof(buffer));
  pb_decode(&i_stream, Student_fields, &unpack_stu);
  printf("unpack_stu.num = %d\r\n", unpack_stu.num);
  printf("unpack_stu.py_score = %d\r\n", unpack_stu.py_score);
  printf("unpack_stu.c_score = %d\r\n", unpack_stu.c_score);
}

输出打印:

unpack_stu.num = 88
unpack_stu.py_score = 90
unpack_stu.c_score = 99

使用proto3

将student.proto修改为:

syntax = "proto3";

message Student
{
  uint32 num      = 1;
  uint32 py_score = 2;
  uint32 c_score  = 3;
}

重新使用

protoc --nanopb_out=. student.proto

可以生成使用proto3语法的student.pb.c和student.pb.h文件

注意

proto2和proto3的语法不能混合使用(即.proto文件要么全为proto2语法要么全为proto3语法),否则生成文件会报错

请添加图片描述

关于proto3语法介绍下篇再做介绍。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值