protobuf

为什么要使用protobuf

结构化数据的几种方式:
1.raw in-memory data structures:二进制存储,但是脆弱,因为读这些数据的代码必须要以同样的内存布局来编译
2.以特定方式编码:比如12:3:-23:67来编码4个整数,语法分析耗时,只能用于简单的数据
3.XML:人类可读,多种语言适配,但是较为复杂

protobuf:灵活、效率高、可扩展
简单
比xml要小3到10倍,proto文件被编译成bin二进制文件
比xml要快20到100倍
结构更加清晰,不会产生歧义
生成数据操作类更加容易,编程更加容易上手,访问接口代码基本都是自动生产

简单使用

https://github.com/protobuf-c/protobuf-c/wiki/Examples

https://developers.google.com/protocol-buffers/docs/cpptutorial

package

防止命名冲突,相当于命名空间

amessage.proto文件

message AMessage {
  required int32 a=1; 
  optional int32 b=2;
}

生成.h 和.c文件

protoc-c --c_out=. amessage.proto 

在这里插入图片描述

链接

-lprotobuf-c

Serialize/pack

construct message :AMESSAGE_INIT
b是否存在(optional才有):msg.has_b
获得packed data的长度:amessage_get_packed_size(&msg)
serializes the message:amessage__pack(&msg, buf)

/*
	构建一个message,并从参数获得值,获得长度,pack,写入缓冲区
*/
#include <stdio.h>
#include <stdlib.h>
#include "amessage.pb-c.h"

int main (int argc, const char * argv[]) 
{
  // 1.构建msg
  AMessage msg = AMESSAGE__INIT; // AMessage
  void *buf;                     // Buffer to store serialized data
  unsigned len;                  // Length of serialized data
  
  if (argc != 2 && argc != 3)
  {   // Allow one or two integers
    fprintf(stderr,"usage: amessage a [b]\n");
    return 1;
  }
  // 2.赋值
  msg.a = atoi(argv[1]);
  if (argc == 3) { msg.has_b = 1; msg.b = atoi(argv[2]); }
  // 3.获得长度
  len = amessage__get_packed_size(&msg);
  
  buf = malloc(len);
  // 4.pack
  amessage__pack(&msg,buf);	//pack
  
  fprintf(stderr,"Writing %d serialized bytes\n",len); // See the length of message
  fwrite(buf,len,1,stdout); // Write to stdout to allow direct command line piping
  
  free(buf); // Free the allocated serialized buffer
  return 0;
}

deserialize/unpack

unpack(先AMessage *msg;):msg = amessage__unpack(NULL, msg_len, buf)
free the unpacked message:amessage__free_unpacked(msg, NULL);

Repeated

message CMessage {
  repeated int32 c=1;
}

c的个数:msg.n_c
访问c数组:msg.c[i]

Submessages

message Submessage {
  required int32 value=1;
}

message EMessage {
  required Submessage a=1;
  optional Submessage b=2;
}

serialize/pack
optional submessages没有has_,如果指针不为空,默认有值

  EMessage msg    = EMESSAGE__INIT;   // EMESSAGE
  Submessage sub1 = SUBMESSAGE__INIT; // SUBMESSAGE A
  Submessage sub2 = SUBMESSAGE__INIT; // SUBMESSAGE B
  sub1.value = atoi (argv[1]); 
  msg.a = &sub1;    				  // 存储的是指向submessage的指针
  sub2.value = atoi (argv[2]); 
  msg.b = &sub2;

  len = emessage__get_packed_size (&msg); // This is the calculated packing length
  buf = malloc (len);                     // Allocate memory
  emessage__pack (&msg, buf);             // Pack msg, including submessages

eserialize/unpack

EMessage *msg;         // EMessage using submessages
Submessage *sub1,*sub2;// Submessages
msg = emessage__unpack(NULL,i,buf); 
sub1 = msg->a;
sub2 = msg->b;

emessage__free_unpacked(msg,NULL);

Repeated Submessages

message Submessage {
  required int32 value=1;
}

message FMessage {
  repeated Submessage a=1;
}

pack

 FMessage msg = FMESSAGE__INIT;
 Submessage **subs;
 
 for (i = 1; i < argc; i++)
  {
    subs[i-1] = malloc (sizeof (Submessage));
    submessage__init (subs[i-1]);
    subs[i-1]->value = atoi(argv[i]);
  }    

 msg.n_a = argc-1;	// a的个数
 msg.a = subs;	//subs赋给a,a是指针的数组
 len = fmessage__get_packed_size (&msg); // This is the calculated packing length
 buf = malloc (len);                     // Allocate memory
 fmessage__pack (&msg, buf);             // Pack msg, including submessages

unpack

FMessage *msg;
msg = fmessage__unpack(NULL,i,buf);
fmessage__free_unpacked(msg,NULL);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值