1. 程式人生 > >【應用筆記】嵌入式領域的protocol buffer原始碼庫:Nanopb

【應用筆記】嵌入式領域的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檔案。

3 proto檔案編譯

        protoc是proto描述檔案的編譯工具,用於生成 *.pb.c*.pb.h檔案,protoc在generator-bin資料夾內,編譯時使用以下命令,第一個引數中的點表示將生成檔案輸出到當前目錄。

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

4 proto檔案描述語法

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;         }     }

}