【应用笔记】嵌入式领域的protocol buffer源码库:Nanopb

1 简介

        Protocol Buffers 是由 google 开发,轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。优点是数据压缩率高,编解码快速, 缺点是编码后的二进制流不具备可读性。Nanopb 是用c语言实现,用于嵌入式领域的protocol buffer源码库,它仅需很小的资源就能运行,编译后代码空间需要2~10K,ram只需要300字节,项目主页地址为 https://jpa.kapsi.fi/nanopb/ 。

        Protocol Buffers 交换的消息格式用proto文件来描述,proto文件会根据对应的语言编译成相应的源文件添加到项目中,函数库在编解码时需要引用这些源文件中的内容。

2 下载

        nanopb每个版本发布有四个包可下载,作为大多数用户,下载对应系统的版本即可,它包含对应系统的代码生成工具及其依赖,用于生成 *.pb.c*.pb.h文件。

        【应用笔记】嵌入式领域的protocol buffer源码库:Nanopb_第1张图片

3 proto文件编译

        protoc是proto描述文件的编译工具,用于生成 *.pb.c*.pb.h文件,protoc在generator-bin文件夹内,编译时使用以下命令,第一个参数中的点表示将生成文件输出到当前目录。

          generator-bin/protoc --nanopb_out=. myprotocol.proto

4 proto文件描述语法

        参考:https://blog.csdn.net/sylar_d/article/details/51325987

5 引用库

       下载最新的版本的nanopb,将以下文件添加到项目中

  •   pb.h
  •   pb_common.h and pb_common.c (必须)
  •   pb_decode.h and pb_decode.c (需要解码时)
  •   pb_encode.h and pb_encode.c (需要编码时)

        继续添加你的protocol buffer描述文件如

  •   myprotocol.pb.c (自动生成,包含常亮初始值)
  •   myprotocol.pb.h (自动生成,包含类型声明)

        接下来就可以开始的业务工作了,可参考examples文件夹中的各种示例,其中simple文件夹为最简单的例子,下面为该例子相关文件的简化内容。

simple.proto:

syntax = "proto3";

message SimpleMessage {
    int32 lucky_number = 1;
}

simple.pb.h:

typedef struct _SimpleMessage {
    int32_t lucky_number;
} SimpleMessage;

#define SimpleMessage_init_default               {0}
#define SimpleMessage_init_zero                  {0}

simple.pb.c:

#include "simple.pb.h"

const pb_field_t SimpleMessage_fields[2] = {
    PB_FIELD(  1, INT32   , SINGULAR, STATIC  , FIRST, SimpleMessage, lucky_number, lucky_number, 0),
    PB_LAST_FIELD
};

simple.c:

int main()
{

    //该缓存会存放编码后的数据
    uint8_t buffer[128];
    size_t message_length;
    bool status;
    // 对一个消息编码
    {
        SimpleMessage message = SimpleMessage_init_zero;
        //定义一个定向目标缓存区的流
        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
        
        message.lucky_number = 13;
        //开始编码消息
        status = pb_encode(&stream, SimpleMessage_fields, &message);
        message_length = stream.bytes_written;
        
        if (!status)
        {
            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
            return 1;
        }
    }

}

你可能感兴趣的:(应用笔记)