一、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
运行结果:
protobuf-c 纯C版本的protobuf移植与使用
最新推荐文章于 2025-05-09 10:20:05 发布