一、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
運行結果: