安装和使用protobuf-c

介绍

Protocol Buffers,是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。它不依赖于语言和平台并且可扩展性极强。

同XML相比,Protocol buffers在序列化结构化数据方面有许多优点:
1. 更简单
2. 数据描述文件只需原来的1/10至1/3
3. 解析速度是原来的20倍至100倍
4. 减少了二义性
5. 生成了更容易在编程中使用的数据访问
6.支持多种编程语言
(转自百度百科)

  • 完整代码放到我的github下了

安装

这里我使用的是 protobuf-c,在安装 protobuf-c 之前需要安装 protobuf

安装protobuf

首先安装依赖 sudo apt-get install autoconf automake libtool curl make g++ unzip

git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make
make check  # make check 失败的话没关系,继续下面的安装
sudo make install
sudo ldconfig

安装protobuf-c

首先安装依赖sudo apt-get install pkg-config pkgconf

git clone https://github.com/protobuf-c/protobuf-c.git
./autogen.sh && ./configure && make && make install

到这里就已经安装好 protobufprotobuf-c

使用protobuf-c

编辑文件student.proto 这里用的是proto2(建议新手直接上 proto3
这里以 student 为例子

syntax = "proto2";

message Student {
    optional string name = 1;
}

命令protoc --c_out=. student.proto
生成.c.h文件 student.pb-c.c student.pb-c.h

不要太关注下面的两个文件

  • 下面是生成的student.pb-c.h
/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: student.proto */

#ifndef PROTOBUF_C_student_2eproto__INCLUDED
#define PROTOBUF_C_student_2eproto__INCLUDED

#include 

PROTOBUF_C__BEGIN_DECLS

#if PROTOBUF_C_VERSION_NUMBER < 1000000
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
#endif


typedef struct _Student Student;


/* --- enums --- */


/* --- messages --- */

struct  _Student
{
  ProtobufCMessage base;
  char *name;
};
#define STUDENT__INIT \
 { PROTOBUF_C_MESSAGE_INIT (&student__descriptor) \
    , NULL }


/* Student methods */
void   student__init
                     (Student         *message);
size_t student__get_packed_size
                     (const Student   *message);
size_t student__pack
                     (const Student   *message,
                      uint8_t             *out);
size_t student__pack_to_buffer
                     (const Student   *message,
                      ProtobufCBuffer     *buffer);
Student *
       student__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data);
void   student__free_unpacked
                     (Student *message,
                      ProtobufCAllocator *allocator);
/* --- per-message closures --- */

typedef void (*Student_Closure)
                 (const Student *message,
                  void *closure_data);

/* --- services --- */


/* --- descriptors --- */

extern const ProtobufCMessageDescriptor student__descriptor;

PROTOBUF_C__END_DECLS


#endif  /* PROTOBUF_C_student_2eproto__INCLUDED */
  • 下面是生成的student.pb-c.c
// student.pb-c.c
/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: student.proto */

/* Do not generate deprecated warnings for self */
#ifndef PROTOBUF_C__NO_DEPRECATED
#define PROTOBUF_C__NO_DEPRECATED
#endif

#include "student.pb-c.h"
void   student__init
                     (Student         *message)
{
  static const Student init_value = STUDENT__INIT;
  *message = init_value;
}
size_t student__get_packed_size
                     (const Student *message)
{
  assert(message->base.descriptor == &student__descriptor);
  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t student__pack
                     (const Student *message,
                      uint8_t       *out)
{
  assert(message->base.descriptor == &student__descriptor);
  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t student__pack_to_buffer
                     (const Student *message,
                      ProtobufCBuffer *buffer)
{
  assert(message->base.descriptor == &student__descriptor);
  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Student *
       student__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data)
{
  return (Student *)
     protobuf_c_message_unpack (&student__descriptor,
                                allocator, len, data);
}
void   student__free_unpacked
                     (Student *message,
                      ProtobufCAllocator *allocator)
{
  if(!message)
    return;
  assert(message->base.descriptor == &student__descriptor);
  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
static const ProtobufCFieldDescriptor student__field_descriptors[1] =
{
  {
    "name",
    1,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_STRING,
    0,   /* quantifier_offset */
    offsetof(Student, name),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
};
static const unsigned student__field_indices_by_name[] = {
  0,   /* field[0] = name */
};
static const ProtobufCIntRange student__number_ranges[1 + 1] =
{
  { 1, 0 },
  { 0, 1 }
};
const ProtobufCMessageDescriptor student__descriptor =
{
  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
  "Student",
  "Student",
  "Student",
  "",
  sizeof(Student),
  1,
  student__field_descriptors,
  student__field_indices_by_name,
  1,  student__number_ranges,
  (ProtobufCMessageInit) student__init,
  NULL,NULL,NULL    /* reserved[123] */
};

在代码里使用

编辑文件 student.c

#include 
#include 
#include 
#include "student.pb-c.h"

#define NAME_LEN 32

int main() {
    Student stu = STUDENT__INIT; // 初始化
    void *buf = NULL;
    unsigned int len;
    Student *msg = NULL;

    stu.name = (char*)malloc(NAME_LEN);
    stu.name = "test";

    len = student__get_packed_size(&stu);  // 算出大小
    printf("size of Student info : %u\n", len);
    buf = malloc(len);
    student__pack(&stu, buf); // 打包

    msg = student__unpack(NULL, len, buf); // 解包
    printf("msg name : %s\n", msg->name);

    student__free_unpacked(msg, NULL); // 释放空间

    free(buf);
    return 0;
}

编译

编译 gcc student.c student.pb-c.c -o student -lprotobuf-c
需要连接 protobuf-c
输出:

size of Student info : 6
msg name : test

2020.3.2 16:40 广州

你可能感兴趣的:(安装和使用protobuf-c)