Tangaoo an embedded software engineer

protobuf

2021-07-19
tangoo

项目中有很多自定义结构体类型的数据需要保存,然后上位机在读取解析用。写了一堆自定义协议的序列化与反序列化代码,又臭又长,而且序列化的协议是 word 文档,也就是协议跟代码是分家的,既然都分家了,那么不一致就不稀奇了。

那么怎么解决这个问题呢,如果 word 协议可以被编解码程序识别那就完美了。protobuf-c 可以正好可以解决这个问题,当然 protobuf-c 还能解决客户端/服务器通信的问题。

1. 安装

  • 安装 protobuf
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make
make check  # make check 失败的话没关系,继续下面的安装
sudo make install
sudo ldconfig

安装不成功的话,检查依赖sudo apt-get install autoconf automake libtool curl make g++ unzip

  • 安装 protobuf-c
git clone https://github.com/protobuf-c/protobuf-c.git
./autogen.sh && ./configure && make && make install

2. protobuf-c 生成协议代码

  • 编辑 student.proto 文件
syntax = "proto3";
  
message Student {
    required int32 id = 1;
    required string name = 2;
    required int32 socre = 3;
}
  • 生成源文件
protoc --c_out=. student.proto

生成.c和.h文件 student.pb-c.c student.pb-c.h

3. 编写代码

  • 编写 student.c 文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.pb-c.h"

#define NAME_LEN 32

int main() {
    Student stu = STUDENT__INIT; // 初始化
    void *buf = NULL;
    unsigned int len;
    Student *msg = NULL;

    stu.name = (char*)malloc(NAME_LEN);
    stu.name = "test";

    len = student__get_packed_size(&stu);  // 算出大小
    printf("size of Student info : %u\n", len);
    buf = malloc(len);
    student__pack(&stu, buf); // 打包

    msg = student__unpack(NULL, len, buf); // 解包
    printf("msg name : %s\n", msg->name);

    student__free_unpacked(msg, NULL); // 释放空间

    free(buf);
    return 0;
}
  • 编译 student.c
gcc student.c student.pb-c.c -o student -lprotobuf-c

注意要链接 protobuf-c 库。

4. 存文件

其实现在存文件还是有问题,没有分隔符。那么解析端无法分隔每条消息。所以还要套一个头标识和长度。比如下面这样:

  +------+------+-------+
  | flag | size | data  |
  +------+------+-------+ 
  |    header   |

5. 在多思考一下

其实也可以不需要用 protoc 工具提前生成代码,只要有一个解析器,在程序运行的时候解析 protoc 协议文件就好了。


Comments

Content