protobuf-c 纯C版本的protobuf移植与使用

一、X86 ubuntu平台

1.下载protobuf-c ,下载最新版本就行

下载地址:https://github.com/protobuf-c/protobuf-c/tags

2.编译与安装

安装依赖库

sudo apt-get install autoconf automake libtool  curl make g++ unzip pkg-config

安装protobuf3(要先安装protobuf2.6.1以上的版本后,才能正常编译出protobuf-c的bin、lib等)

下载地址:https://github.com/protocolbuffers/protobuf/tags

解压后,进入解压目录,执行以下命令(可以看下src/README.md的说明)

  git submodule update --init --recursive(如果不是从git仓库clone下来的源码,可忽略)
  ./autogen.sh(如果不是从git仓库clone下来的源码,可忽略)

  ./configure
  make
  make check
  sudo make install
  sudo ldconfig # refresh shared library cache.

编译protobuf-c

    ./autogen.sh (如果不是从git仓库clone下来的源码,可忽略)

  ./configure --prefix=xxx/xxx/protobuf-c-x86(--prefix选一个自定义的目录,可以不加这选项,默认安装的系统文件夹)

   make

   make install

至此,protobuf-c安装完成。

3.protobuf-c移植至ARM

  ./autogen.sh
  ./configure --host=arm-linux CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ --disable-protoc --prefix=/usr/local/protobuf-c-arm
CC=指定gcc编译器,CXX=指定g++编译器,--disable-protoc 不使用protoc(因为它是C++版本,此处只用它生成两个文件,编译处用不到,除非在arm机器上编译protoc代码才会用到),--prefix=指定安装路径
如果arm-gcc编译器不会自动寻找依赖的h和lib,有时还需要指定

CFLAG、LDFLAGS、CPP即$(CC) -E 、CXXCPP即$(CXX) -E   、LD 、AR

可以暴力的将CFLAG、LDFLAGS加到CC="arm-none-linux-gnueabi-gcc $(CFLAGS)  $(LDFLAGS)"后面,防止arm-gcc编译器找不到依赖头文件或库文件,导致configure、编译或链接失败

4.protobuf-c的使用

编写.proto文件,如test.proto

syntax="proto2";//标记使用proto V2版本,现在最新已经是V3版本,支持C++、JAVA等主流语言,C还不支持
/*以下为测试数据*/
message TestMessage{
optional uint64 id=1;
repeated uint32 state=2;
required string name=3;
}

message AllMessage{
required bytes data=1;
required uint64 all_id=2;
required uint32 all_state=3;
required TestMessage testmsg=4;
}

  字段规则类型:

  required:表示后面的数据是必须的。

  optional:表示后面数据是可选的。

  repeated:表示后面的数据是一个数组

 

  生成.pb-c.c和.pb-c.h文件

  可以将.proto文件复制到安装目录(xxx/xxx/protobuf-c-x86/bin),即proto-c可执行文件所在目录,终端执行

  ./protoc-c -I=. --c_out=. ./test.proto

  可以生成test.pb-c.c和test.pb-c.h文件

  如果安装在系统文件夹

  可以在test.proto所在的文件夹,终端执行

  protoc-c -I=. --c_out=. ./test.proto

使用.pb-c.c和.pb-c.h文件
test.pb-c.c
/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test.proto */

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

#include "test.pb-c.h"
void   test_message__init
                     (TestMessage         *message)
{
  static const TestMessage init_value = TEST_MESSAGE__INIT;
  *message = init_value;
}
size_t test_message__get_packed_size
                     (const TestMessage *message)
{
  assert(message->base.descriptor == &test_message__descriptor);
  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t test_message__pack
                     (const TestMessage *message,
                      uint8_t       *out)
{
  assert(message->base.descriptor == &test_message__descriptor);
  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t test_message__pack_to_buffer
                     (const TestMessage *message,
                      ProtobufCBuffer *buffer)
{
  assert(message->base.descriptor == &test_message__descriptor);
  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
TestMessage *
       test_message__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data)
{
  return (TestMessage *)
     protobuf_c_message_unpack (&test_message__descriptor,
                                allocator, len, data);
}
void   test_message__free_unpacked
                     (TestMessage *message,
                      ProtobufCAllocator *allocator)
{
  if(!message)
    return;
  assert(message->base.descriptor == &test_message__descriptor);
  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void   all_message__init
                     (AllMessage         *message)
{
  static const AllMessage init_value = ALL_MESSAGE__INIT;
  *message = init_value;
}
size_t all_message__get_packed_size
                     (const AllMessage *message)
{
  assert(message->base.descriptor == &all_message__descriptor);
  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t all_message__pack
                     (const AllMessage *message,
                      uint8_t       *out)
{
  assert(message->base.descriptor == &all_message__descriptor);
  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t all_message__pack_to_buffer
                     (const AllMessage *message,
                      ProtobufCBuffer *buffer)
{
  assert(message->base.descriptor == &all_message__descriptor);
  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
AllMessage *
       all_message__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data)
{
  return (AllMessage *)
     protobuf_c_message_unpack (&all_message__descriptor,
                                allocator, len, data);
}
void   all_message__free_unpacked
                     (AllMessage *message,
                      ProtobufCAllocator *allocator)
{
  if(!message)
    return;
  assert(message->base.descriptor == &all_message__descriptor);
  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
static const ProtobufCFieldDescriptor test_message__field_descriptors[3] =
{
  {
    "id",
    1,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_UINT64,
    offsetof(TestMessage, has_id),
    offsetof(TestMessage, id),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "state",
    2,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_UINT32,
    offsetof(TestMessage, n_state),
    offsetof(TestMessage, state),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "name",
    3,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_STRING,
    0,   /* quantifier_offset */
    offsetof(TestMessage, name),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
};
static const unsigned test_message__field_indices_by_name[] = {
  0,   /* field[0] = id */
  2,   /* field[2] = name */
  1,   /* field[1] = state */
};
static const ProtobufCIntRange test_message__number_ranges[1 + 1] =
{
  { 1, 0 },
  { 0, 3 }
};
const ProtobufCMessageDescriptor test_message__descriptor =
{
  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
  "TestMessage",
  "TestMessage",
  "TestMessage",
  "",
  sizeof(TestMessage),
  3,
  test_message__field_descriptors,
  test_message__field_indices_by_name,
  1,  test_message__number_ranges,
  (ProtobufCMessageInit) test_message__init,
  NULL,NULL,NULL    /* reserved[123] */
};
static const ProtobufCFieldDescriptor all_message__field_descriptors[4] =
{
  {
    "data",
    1,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_BYTES,
    0,   /* quantifier_offset */
    offsetof(AllMessage, data),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "all_id",
    2,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_UINT64,
    0,   /* quantifier_offset */
    offsetof(AllMessage, all_id),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "all_state",
    3,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_UINT32,
    0,   /* quantifier_offset */
    offsetof(AllMessage, all_state),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "testmsg",
    4,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_MESSAGE,
    0,   /* quantifier_offset */
    offsetof(AllMessage, testmsg),
    &test_message__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
};
static const unsigned all_message__field_indices_by_name[] = {
  1,   /* field[1] = all_id */
  2,   /* field[2] = all_state */
  0,   /* field[0] = data */
  3,   /* field[3] = testmsg */
};
static const ProtobufCIntRange all_message__number_ranges[1 + 1] =
{
  { 1, 0 },
  { 0, 4 }
};
const ProtobufCMessageDescriptor all_message__descriptor =
{
  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
  "AllMessage",
  "AllMessage",
  "AllMessage",
  "",
  sizeof(AllMessage),
  4,
  all_message__field_descriptors,
  all_message__field_indices_by_name,
  1,  all_message__number_ranges,
  (ProtobufCMessageInit) all_message__init,
  NULL,NULL,NULL    /* reserved[123] */
};

test.pb-c.h

/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test.proto */

#ifndef PROTOBUF_C_test_2eproto__INCLUDED
#define PROTOBUF_C_test_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 1004000 < 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 TestMessage TestMessage;
typedef struct AllMessage AllMessage;


/* --- enums --- */


/* --- messages --- */

/*
 *以下为测试数据
 */
struct  TestMessage
{
  ProtobufCMessage base;
  protobuf_c_boolean has_id;
  uint64_t id;
  size_t n_state;
  uint32_t *state;
  char *name;
};
#define TEST_MESSAGE__INIT \
 { PROTOBUF_C_MESSAGE_INIT (&test_message__descriptor) \
    , 0, 0, 0,NULL, NULL }


struct  AllMessage
{
  ProtobufCMessage base;
  ProtobufCBinaryData data;
  uint64_t all_id;
  uint32_t all_state;
  TestMessage *testmsg;
};
#define ALL_MESSAGE__INIT \
 { PROTOBUF_C_MESSAGE_INIT (&all_message__descriptor) \
    , {0,NULL}, 0, 0, NULL }


/* TestMessage methods */
void   test_message__init
                     (TestMessage         *message);
size_t test_message__get_packed_size
                     (const TestMessage   *message);
size_t test_message__pack
                     (const TestMessage   *message,
                      uint8_t             *out);
size_t test_message__pack_to_buffer
                     (const TestMessage   *message,
                      ProtobufCBuffer     *buffer);
TestMessage *
       test_message__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data);
void   test_message__free_unpacked
                     (TestMessage *message,
                      ProtobufCAllocator *allocator);
/* AllMessage methods */
void   all_message__init
                     (AllMessage         *message);
size_t all_message__get_packed_size
                     (const AllMessage   *message);
size_t all_message__pack
                     (const AllMessage   *message,
                      uint8_t             *out);
size_t all_message__pack_to_buffer
                     (const AllMessage   *message,
                      ProtobufCBuffer     *buffer);
AllMessage *
       all_message__unpack
                     (ProtobufCAllocator  *allocator,
                      size_t               len,
                      const uint8_t       *data);
void   all_message__free_unpacked
                     (AllMessage *message,
                      ProtobufCAllocator *allocator);
/* --- per-message closures --- */

typedef void (*TestMessage_Closure)
                 (const TestMessage *message,
                  void *closure_data);
typedef void (*AllMessage_Closure)
                 (const AllMessage *message,
                  void *closure_data);

/* --- services --- */


/* --- descriptors --- */

extern const ProtobufCMessageDescriptor test_message__descriptor;
extern const ProtobufCMessageDescriptor all_message__descriptor;

PROTOBUF_C__END_DECLS


#endif  /* PROTOBUF_C_test_2eproto__INCLUDED */

main.c

#include "test.pb-c.h"
#include <stdio.h>
#include "unistd.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, char **argv)
{
    printf("compile date:%s %s\n", __DATE__, __TIME__);
        TestMessage test_msg = TEST_MESSAGE__INIT;
        AllMessage all_msg = ALL_MESSAGE__INIT;
        test_msg.name = calloc(1, 32);
        memcpy(test_msg.name,"helloworld",strlen("helloworld"));
        test_msg.id = 12345678;
        test_msg.n_state = 8;
        test_msg.state = calloc(test_msg.n_state,sizeof(uint32_t));
        for (int i = 0; i < 8; i++)
        {
            test_msg.state[i] = i * i;
        }
        all_msg.testmsg = &test_msg;
        all_msg.data.len = 32;
        all_msg.data.data = calloc(1, all_msg.data.len);
        all_msg.all_id = 87654321;
        all_msg.all_state = 1234;
        int pack_len = all_message__get_packed_size(&all_msg);
        char *pack_buf = NULL;
        pack_buf = (char *)calloc(1, pack_len);
        if (!pack_len)
        {
            printf("calloc error\n");
            return -1;
        }
        int unpack_len=all_message__pack(&all_msg, pack_buf);
        printf("get size=%d %d\n", pack_len,unpack_len);
        AllMessage *all_unpack = all_message__unpack(NULL, pack_len,pack_buf);
        printf("unpack name:%s\n", all_unpack->testmsg->name);
        for (int i = 0; i < 8; i++)
        {
            printf("all_unpack->testmsg->state[%d]=%d\n",i,all_unpack->testmsg->state[i]);
        }
        all_message__free_unpacked(all_unpack, NULL);
        free(test_msg.name );
        free(test_msg.state);
        free(all_msg.data.data);
        free(pack_buf);
    return 0;
}

build.sh

gcc main.c test.pb-c.c -o test_proto -I. -L./lib -I./include -lprotobuf-c

运行结果:

 

 




posted @ 2021-10-19 10:03  jest549  阅读(7112)  评论(0编辑  收藏  举报