protobuf有个开源c库,叫做nanopb,可以实现对protobuf的加密和解密。
项目地址:
https://github.com/nanopb/nanopb
项目的主页写的很清楚,使用方法为编译.proto文件,然后把各个文件包含进工程就可以了。
To use the nanopb library, you need to do two things:
- Compile your .proto files for nanopb, using
protoc
.- Include pb_encode.c, pb_decode.c and pb_common.c in your project.
例如,编译simple.proto
nanopb-0.4.7-windows-x86\generator-bin>nanopb_generator.exe simple.proto
Writing to simple.pb.h and simple.pb.c
产生的simple.pb.h,simple.pb.c文件就是可以拷贝进工程的文件。再加上原本的库文件pb.h, pb_common.c/.h, pb_encode.c/.h, pb_decode.c/.h文件,就可以正常使用了。
对于.proto文件的格式,如下有个大概的例子:
// A very simple protocol definition, consisting of only
// one message.
syntax = "proto2";import "nanopb.proto";
message SimpleMessage {
required int32 lucky_number = 1;
required float float_number = 2;
required string name = 3 [(nanopb).max_size = 40];
repeated bool num = 4 [(nanopb).max_count = 5];
repeated int32 ids = 5 [(nanopb).max_count = 5];
repeated int32 array = 6 [(nanopb).max_count = 5, (nanopb).int_size = IS_8];
}
产生的simple.pb.h文件如下,可以对比知道怎么编写各种类型的数据和数组:
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.7 */
#ifndef PB_SIMPLE_PB_H_INCLUDED
#define PB_SIMPLE_PB_H_INCLUDED
#include
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Struct definitions */
typedef struct _SimpleMessage {
int32_t lucky_number;
float float_number;
char name[40];
pb_size_t num_count;
bool num[5];
pb_size_t ids_count;
int32_t ids[5];
pb_size_t array_count;
int8_t array[5];
} SimpleMessage;
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define SimpleMessage_init_default {0, 0, "", 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}}
#define SimpleMessage_init_zero {0, 0, "", 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}}
/* Field tags (for use in manual encoding/decoding) */
#define SimpleMessage_lucky_number_tag 1
#define SimpleMessage_float_number_tag 2
#define SimpleMessage_name_tag 3
#define SimpleMessage_num_tag 4
#define SimpleMessage_ids_tag 5
#define SimpleMessage_array_tag 6
/* Struct field encoding specification for nanopb */
#define SimpleMessage_FIELDLIST(X, a) \
X(a, STATIC, REQUIRED, INT32, lucky_number, 1) \
X(a, STATIC, REQUIRED, FLOAT, float_number, 2) \
X(a, STATIC, REQUIRED, STRING, name, 3) \
X(a, STATIC, REPEATED, BOOL, num, 4) \
X(a, STATIC, REPEATED, INT32, ids, 5) \
X(a, STATIC, REPEATED, INT32, array, 6)
#define SimpleMessage_CALLBACK NULL
#define SimpleMessage_DEFAULT NULL
extern const pb_msgdesc_t SimpleMessage_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define SimpleMessage_fields &SimpleMessage_msg
/* Maximum encoded size of messages (where known) */
#define SimpleMessage_size 177
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
用vc写个测试程序:
// protobuf_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "stdio.h"
#include "pb_encode.h"
#include "pb_decode.h"
#include "simple.pb.h"
int main(void)
{
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;
}
else
{
printf("encode protobuf ok, len=%d\r\n", message_length);
}
}
{
SimpleMessage message = SimpleMessage_init_zero;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
status = pb_decode(&stream, SimpleMessage_fields, &message);
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
else
{
printf("Your lucky number was %d!\n", (int)message.lucky_number);
}
}
return 0;
}
输出为:
encode protobuf ok, len=2
Your lucky number was 13!