假设已经有protobuf的基础
Nanopb 用于以 Google 的 Protobuf 格式编码和解码消息,对RAM和代码空间的要求很低。它主要适用于 32 位微控制器。 总的来说就是编码(压缩)-传递-解码(解压)
因此,你手里的某个项目的项目可能包括以下文件: Nanopb 运行时库:
- pb.h
- pb_common.h 和 pb_common.c(始终需要)
- pb_decode.h 和 pb_decode.c(解码消息时需要)
- pb_encode.h 和 pb_encode.c(编码消息时需要)
协议描述(您可以有很多):
- person.proto(只是一个例子)
- person.pb.c(自动生成,包含消息描述符)
- person.pb.h(自动生成,包含类型声明和宏)
其他介绍参阅:官方介绍
GitHub源码:https://github.com/nanopb/nanopb
稳定版下载:https ://jpa.kapsi.fi/nanopb/download/
下载新版的比如
nanopb-0.4.6-linux-x86.tar.gz
,解压
将解压后的generator-bin
文件夹添加到环境变量
gedit ~/.bashrc
,末尾加上
export PATH=$PATH:/home/aillian/nanopb/nanopb-0.4.6-linux-x86/generator-bin/
这样我们就可以在终端使用
nanopb_generator -D ${OUT_DIR} xxx.proto
protoc --nanopb_out=${OUT_DIR} xxx.proto
生成对应的xxx.pb.c
和xxx.pb.h
文件
ps:我系统找不到--nanopb_out
这个选项,有好心人找到原因了请留言告诉我,不过用nanopb_generator
效果是一样的,生成的文件没有区别
有关简单情况的完整示例,请参阅示例/简单/simple.c。有关具有网络接口的更复杂的示例,请参阅示例/network_server子目录。
简单的编码和解码示例
#include <stdio.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "simple.pb.h"
int main()
{
/* This is the buffer where we will store our message. */
uint8_t buffer[128];
size_t message_length;
bool status;
/* Encode our message */
{
/* Allocate space on the stack to store the message data.
*
* Nanopb generates simple struct definitions for all the messages.
* - check out the contents of simple.pb.h!
* It is a good idea to always initialize your structures
* so that you do not have garbage data from RAM in there.
*/
SimpleMessage message = SimpleMessage_init_zero;
/* Create a stream that will write to our buffer. */
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/* Fill in the lucky number */
message.lucky_number = 13;
/* Now we are ready to encode the message! */
status = pb_encode(&stream, SimpleMessage_fields, &message);
message_length = stream.bytes_written;
/* Then just check for any errors.. */
if (!status)
{
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
}
/* Now we could transmit the message over network, store it in a file or
* wrap it to a pigeon's leg.
*/
/* But because we are lazy, we will just decode it immediately. */
{
/* Allocate space for the decoded message. */
SimpleMessage message = SimpleMessage_init_zero;
/* Create a stream that reads from the buffer. */
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
/* Now we are ready to decode the message. */
status = pb_decode(&stream, SimpleMessage_fields, &message);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
/* Print the data contained in the message. */
printf("Your lucky number was %d!\n", (int)message.lucky_number);
}
return 0;
}
官方文档:https://jpa.kapsi.fi/nanopb/docs/concepts.html
基础用法例子 有关简单情况的完整示例,请参阅示例/简单/simple.c。有关具有网络接口的更复杂的示例,请参阅示例/network_server子目录。
.
├── build
├── CMakeLists.txt
└── modules
├── app
│ └── simple.c
└── common
└── data_struct
└── proto
└── data_struct.proto
syntax = "proto2";
message MySimpleMessage {
optional int32 my_number = 1;
}
#include <stdio.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "data_struct.pb.h"
int main()
{
uint8_t mysimplemessagebuf[MySimpleMessage_size];
memset(mysimplemessagebuf, 0, MySimpleMessage_size);
size_t message_length;
// Encode our message
{
MySimpleMessage message;
message.my_number = 15;
pb_ostream_t enc_stream = pb_ostream_from_buffer(mysimplemessagebuf, MySimpleMessage_size);
if (!pb_encode(&enc_stream, MySimpleMessage_fields, &message)) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&enc_stream));
} else {
message_length = enc_stream.bytes_written;
}
}
// Decode our message
{
MySimpleMessage message;
pb_istream_t dec_stream = pb_istream_from_buffer(mysimplemessagebuf, message_length);
if (!pb_decode(&dec_stream, MySimpleMessage_fields, &message)) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&dec_stream));
}
printf("Your lucky number was %d!\n", (int)message.my_number);
}
return 0;
}
cmake_minimum_required(VERSION 2.8)
project(NANOPB_CMAKE_SIMPLE C)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
# change to your nanopb dir
set(CMAKE_MODULE_PATH /home/aillian/nanopb/nanopb-0.4.6-linux-x86/extra)
set(SOURCES ${CMAKE_SOURCE_DIR}/modules/app/simple.c)
find_package(Nanopb REQUIRED)
include_directories(${NANOPB_INCLUDE_DIRS})
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS
${CMAKE_SOURCE_DIR}/modules/common/data_struct/proto/data_struct.proto
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g -O0")
add_executable(exe ${SOURCES} ${PROTO_SRCS} ${PROTO_HDRS})
配合API参考就很容易理解了