protobuf C应用于嵌入式序列化与反序列化

一.简介

protobuf是一种google开源的序列化,反序列化工具
该工具由protoc-c应用程序protobuf-c动态库两部分组成。

二.使用步骤

(1). 提供自定义的xxx.proto文件,来定义你要序列化和反序列化的类型.
(2). 通过proto-c应用程序,为xxx.proto生成相应的xxx.pb-c.h,xxx.pb-c.c这样的代码文件
生成的代码文件包含了xxx.proto类型的定义,并提供了类型序列化,反向序列化的功能实现.
(3). 现在应用程序需要对xxx.proto中类型执行序列化或反序列化处理时,只需编译时,一起编译xxx.pb-c.c源文件,且编译链接和运行链接时,链接到protobuf-c动态库.这样在应用程序代码中就可引用xxx.pb-c.h中的类型,并调用类型的序列化,反向序列化方法实现类型实例的序列化处理,反向序列化处理.

三.应用场景

protobuf-c 可广泛应用于以下场景:

嵌入式系统:由于其小体积和跨平台特性,非常适合在资源有限的设备上使用。
网络通信:通过配合RPC框架,实现高效的数据交换。
数据持久化:将结构化数据序列化到磁盘,然后在程序启动时进行反序列化,以节省内存和提高读写速度。

四.使用方法

1. windows使用方法

下载protoc.exe,protoc.jar
https://download.csdn.net/download/qq_32348883/89750388

  1. proto文件, protoc.exe, protoc.jar放在同一个文件夹中;
  2. 执行java -jar protoc.jar your.proto
  3. 编写调用接口测试用的demo;
  4. protobuf_c.c, protobuf_c.h加入工程一起编译;
  5. 运行。

C接口使用例子

#include "MyProto.h"

static const char hexdig[] = "0123456789abcdef";
static void log_hex(const char* tag, unsigned char* data, int len)
{
    char msg[50], *ptr;
    int i;
    ptr = msg;

    printf("%s\r\n", tag);
    for(i=0; i<len; i++) {
        *ptr++ = hexdig[0x0f & (data[i] >> 4)];
        *ptr++ = hexdig[0x0f & data[i]];
        if ((i & 0x0f) == 0x0f) {
            *ptr = '\0';
            ptr = msg;
            printf("%s\r\n", msg);
        } else {
            *ptr++ = ' ';
        }
    }
    if (i & 0x0f) {
        *ptr = '\0';
        printf("%s\r\n", msg);
    }
}

#define PB_STR(str) {(uint8_t*)str, (uint32_t)strlen(str)}

int main(int argc, char *argv[])
{
    uint8_t* data;
    int out_len;
    
    {
        MyType mytype;
        MyProto myproto;

        MyType_init(&mytype);
        MyType_set_i32(&mytype, 123);

        MyProto_init(&myproto);
        MyProto_set_i32(&myproto, 456);
        MyProto_set_i64(&myproto, 789);
        pb_string str = PB_STR("hello");
        MyProto_set_str(&myproto, &str);
        MyProto_set_msg(&myproto, &mytype);

        data = MyProto_to_byte_array(&myproto, &out_len);
        log_hex("", data, out_len);
    }

    {
        MyProto myproto;
        MyProto_init(&myproto);
        MyProto_from_byte_array(&myproto, data, out_len);
        printf("%.*s", myproto.str.size, myproto.str.data);

    }


    return a.exec();
}

2 linux使用方法

1部分–编译protobuf-c

下载
https://github.com/protobuf-c/protobuf-c

(1)交叉编译protobuf-c

首先在protobuf-c目录下使用make clean命令清除我们之前编译得到的东西:
在这里插入图片描述
输入如下命令生成交叉编译的Makefile文件:

./configure --host=arm-linux-gnueabihf CC=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-gcc CXX=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-g++ --disable-protoc --prefix=$PWD/tmp

在这里插入图片描述
这个命令似乎很长,但并不难,只是加了几个配置参数。这些配置参数怎么看?我们可以输入./configure --help命令来查看支持的配置:
在这里插入图片描述
下面我们依次来分析上面那个很长的命令:

  • –host=arm-linux-gnueabihf:表明了我们最终可执行文件运行的环境。

  • CC=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-gcc:这是指定我们的交叉编译工具arm-linux-gnueabihf-gcc,这里直接给出绝对路径。

  • CXX=/home/book/ToolChain/gcc-arm-linux-gnueabihf-6.2.1/bin/arm-linux-gnueabihf-g++:这是指定我们的交叉编译工具arm-linux-gnueabihf-g++,这里直接给出绝对路径。

  • –disable-protoc:不使用protoc,前面我们也说了protoc工具把.proto文件生成对应的C源、头文件的过程是与平台无关的,所以这里不需要使用,除非我们想在我们的开发板上使用protoc,但这反而增加麻烦,不推荐直接在开发板上用。

  • –prefix=$PWD/tmp:指定安装的路径。表明安装路径在当前路径下的tmp文件夹中。

执行完这个命令之后就得到了交叉编译的Makefile文件,然后依次输入如下命令进行编译、安装:

make
make install

在这里插入图片描述
此时就在当前目录的tmp文件夹下生成了arm版本的相关库文件:
在这里插入图片描述
其中我们比较重要的就是libprotobuf-c.so这个动态库了,我们可以使用file或者readelf工具查看其是不是arm格式的:
在这里插入图片描述

2部分–使用protobuf-c

我们自定义一个.proto来创建我们的协议数据,然后使用protoc-c工具编译生成C代码,有两个文件:一个头文件、一个源文件。

例如我们创建一个student.proto文件

syntax = "proto2";
 
message Student
{
    required string name    = 1;
    required uint32 num     = 2;
    required uint32 c_score = 3;
}

使用protoc-c工具工具编译student.proto文件:

protoc --c_out=. student.proto

在这里插入图片描述
编写我们的student.c测试demo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.pb-c.h"
 
int main(void)
{
    Student pack_stu = {0};
    uint8_t buffer[512] = {0};
    Student *unpack_stu = NULL;
    size_t len = 0;
 
    student__init(&pack_stu);
 
    /* 组包 */
    pack_stu.name = "ZhengN";
    pack_stu.num = 88;
    pack_stu.c_score = 90;
    len = student__pack(&pack_stu, buffer);
    printf("len = %ld\n",len);
 
    /* 解包 */
    unpack_stu = student__unpack(NULL, len, buffer);
    printf("unpack_stu.name = %s\n", unpack_stu->name);
    printf("unpack_stu.num = %d\n", unpack_stu->num);
    printf("unpack_stu.c_score = %d\n", unpack_stu->c_score);
 
    student__free_unpacked(unpack_stu, NULL);
    return 0;
}

demo很简单,组包就是构造一个协议数据结构体,调用pack组包接口往buffer中扔数据;解包正好是反过来,从buffer中拿数据放到结构体里。

此时我们工程的文件有:
在这里插入图片描述
编译运行

arm-linux-gnueabihf-gcc student.c student.pb-c.c -o student -I /home/book/git_clone/protobuf-c/tmp/include -L /home/book/git_clone/protobuf-c/tmp/lib -lprotobuf-c

编译没问题的话就可以生成我们的可执行文件student:
在这里插入图片描述
同样的,我们可以看一下student可执行文件的运行环境:
在这里插入图片描述
可见,是可运行在我们的arm开发板的。

运行出现如下错误:
在这里插入图片描述
这是因为不能找到共享库文件libprotobuf-c.so1,加载失败。

解决方法有两种第一种就是把这个库文件拷贝至系统库默认搜索路径下;第二种就是把当前路径增加为动态库的搜索路径

这里我们选择第二种方法:我们把libprotobuf-c.so、libprotobuf-c.so1也传到板子上,放在student同目录下。然后输入如下命令把当前路径增加为动态库的搜索路径:

export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH

然后运行:
在这里插入图片描述

protobuf反序列化函数是用于protobuf格式的数据转换为对的数据结构的函数。根据引用提供的信息,pjcore库是一个跨平台库,其中包含了用于处理protobuf和HTTP的功能。因此,可以在pjcore库中找到protobuf反序列化函数。由于没有具体的函数名提供,无法给出具体的反序列化函数。但是,你可以通过参考pjcore库的文档或源代码来查找和使用protobuf反序列化函数。如果你对pjcore库感兴趣,可以通过引用和引用提供的链接下载源代码并查看相关部分。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [pjcore:C++中protobuf +嵌入式HTTP服务器和客户端的JSON [反]序列化](https://download.csdn.net/download/weixin_42109178/20065407)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [protobuf入门教程(三):常用序列化/反序列化接口](https://blog.csdn.net/tennysonsky/article/details/73920767)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值