美文网首页
安装和使用protobuf-c

安装和使用protobuf-c

作者: besmallw | 来源:发表于2020-03-02 16:41 被阅读0次

    介绍

    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/protobuf-c.h>
    
    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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #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

          本文链接:https://www.haomeiwen.com/subject/ggsvkhtx.html