protocol buffers简单的解释就是,类似与json,xml储存数据的一种格式。
优点:空间效率高。缺点:二进制格式,不易阅读。
release地址,这里要说明一下,找开源不要去github直接下载最新的,而是要下载release版本,因为release稳定性高些:https://github.com/protocolbuffers/protobuf/releases
编译:cd $(OPENSOURCE_LIB_BUILD_PWD) && ./configure --prefix=$(OPENSOURCE_INSTALL_PWD) --host=$(CROSS_COMPILE) && make clean && make && make install
我非常纳闷的问题,同一个源码3.13,以前可以正常编译,现在出现了错误:
##################提示以下错误,以前可以正常编译,但出现下面错误,不编译shared文件即可。
##################./.libs/libprotoc.so: error: undefined reference to 'scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto'
##################./.libs/libprotoc.so: error: undefined reference to 'descriptor_table_google_2fprotobuf_2fdescriptor_2eproto'
现在取消动态库编译,避免这个问题:
./autogen.sh && ./configure --prefix=$(OPENSOURCE_INSTALL_PWD) --host=$(CROSS_COMPILE) --enable-shared=no CC=$(CROSS_COMPILE)-gcc CXX=$(CROSS_COMPILE)-g++
make
make install
或者使用cmake,我使用cmake也可以看到他并没有生成动态库!!!:
cmake . -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$(OPENSOURCE_INSTALL_PWD) -DCMAKE_CXX_COMPILER=$(CROSS_COMPILE)-g++ -DCMAKE_C_COMPILER=$(CROSS_COMPILE)-gcc
make
make install
使用例子:
先写一个:xxx.proto文件,这个文件用于生成.cc和.h文件,以便我们调用API。
surTeacherInfMsg.proto内容如下:
//备注:
//1.syntax表示指定版本,我们用最新的版本proto3。
//2.package定义一个域名,在c++语言调用时需要加上:surTeacherwork::xxx。
//3.message定义一个结构体,用于结构体转数组和数组转结构体。
//4.required必填内容,proto3废除。
/*5.optional可选,proto3也可不要,如果添加optional,在执行protoc命令时需要加
--experimental_allow_proto3_optional。*/
//6.在proto3中取消默认值,默认值为0,或空。
/*7.结构体中,每个成员变量都有一个编号1,2,3,4... 很重要。PROTOBUF是通过这个编号来编解码的,
如果编码和解码的结构体对应编号和类型不一致,就会导致错误。teacherInfNewDef和teacherInfDef
中"int32 id = 1; optional int32 age = 2; optional string add = 3; string res7 =
4;"是一致的,teacherInfNewDef新增了"optional float res5 = 5; int32 res6 = 6;"内容。
teacherInfDef可以解析teacherInfNewDef内容,而teacherInfNewDef解析teacherInfDef内容时,
res5和res6为0,字符串为空。*/
8.string是字符串,如果要用到二进制数组,使用bytes
//这里的message定义结构体
syntax = "proto3";
package surTeacherwork;
message teacherInfDef
{
//required is not used in proto3
int32 id = 1;
optional int32 age = 2;
optional string add = 3;
string res7 = 4;
}
message teacherListInfDef
{
int32 buflen = 1;
repeated teacherInfDef teacher = 2;
}
message teacherInfNewDef
{
//required is not used in proto3
int32 id = 1;
optional int32 age = 2;
optional string add = 3;
string res7 = 4;
optional float res5 = 5;
int32 res6 = 6;
}
message teacherListInfNewDef
{
int32 buflen = 1;
repeated teacherInfNewDef teacher = 2;
}数据类型参考:(三)ProtoBuf数据类型 - 比特边界 - 博客园

第二个文件:surStudentInfMsg.proto,里面有bytes的用法
syntax = "proto3";
package surwork;
enum Direction {
START = 0;
EAST = 1;
SOUTH = 2;
WEST = 3;
NORTH = 4;
};
message studentInfDef
{
//required is not used in proto3
int32 id = 1;
int32 age = 2;
string add = 3;
Direction dir = 4;
optional string res1 = 5;
//string cannot save bin string, bytes can do that.
optional bytes res2 = 6;
optional int32 res3 = 7;
optional int32 res4 = 8;
float res5 = 9;
}
message studentListInfDef
{
//string tbname;
int32 buflen = 1;
repeated studentInfDef student = 2;
}生成.cc文件:
protoc --experimental_allow_proto3_optional -I=. --cpp_out=. surTeacherInfMsg.proto;
protoc --experimental_allow_proto3_optional -I=. --cpp_out=. surStudentInfMsg.proto;
使用:
//备注:
//1.surTeacherwork就是域名
//2.teacherListInfDef时proto生成的类。
/*3.新老版本公共的参数,变量类型和序列号要保持一致!int型变量名"id"序列号都要为1,
string型变量"add"序列号都要为3。参考proto设计*/
//老版本编码(SerializeToString),新版本解码(ParseFromString)
void testProtoBuff1()
{
//zlibCompressClass tempCompressWork = zlibCompressClass(10 * 1024 * 1024);
zlibCompressClass tempCompressWork = zlibCompressClass();
surwork::studentListInfDef saveinf;
surwork::studentListInfDef parseinf;
surwork::studentInfDef *tmpstud;
string mypackstr, zlibencode, zlibuncode;
timerc tnowg;
char mytmps[4];// = {(char)0x1, (char)0x2, (char)0x3, (char)0x4, (char)0xdf};
int i;
printfdbg("begin");
for (i = 0; i < STUDENT_BUF_MAX_LEN; i++)
{
tmpstud = saveinf.add_student();
tmpstud->set_id(i);
tmpstud->set_age(i % 2);
tmpstud->set_dir((surwork::Direction)(i % (surwork::NORTH + 1)));
tmpstud->set_res1("jfdfjk");
for(int j = 0; j < 4; j++)
{
mytmps[j] = (i >> (j * 8)) & 0xff;
}
tmpstud->set_res2(mytmps, sizeof(mytmps));
tmpstud->set_res3(2);
}
printfdbg("generate finish: used time = %fs", tnowg.ints());
tnowg.begin();
saveinf.set_buflen(STUDENT_BUF_MAX_LEN);
if (!saveinf.SerializeToString(&mypackstr))
{
printfdbg("");
return;
}
printfdbg("%ld", mypackstr.length());
printfdbg("to stirng: used time = %fs", tnowg.ints());
tnowg.begin();
if(tempCompressWork.compress(mypackstr, zlibencode))
{
printfdbg("");
return;
}
printfdbg("%ld", zlibencode.length());
printfdbg("compress: used time = %fs", tnowg.ints());
tnowg.begin();
if(tempCompressWork.umcompress(zlibencode, zlibuncode))
{
printfdbg("");
return;
}
printfdbg("%ld", zlibuncode.length());
printfdbg("uncompress: used time = %fs", tnowg.ints());
tnowg.begin();
if (!parseinf.ParseFromString(zlibuncode))
{
printfdbg("");
return;
}
printfdbg("%d, %d, %.3f", parseinf.buflen(), parseinf.student_size(), tnowg.ints());
printfdbg("to inf: used time = %fs", tnowg.ints());
tnowg.begin();
for (int i = 0; i < parseinf.student_size(); i++)
{
surwork::studentInfDef tmpsifget = parseinf.student(i);
string myresstr = tmpsifget.res2();
// printfdbg("%d,%d,%s,%d,%s,%s,%d,%d,%f", tmpsifget.id(), tmpsifget.age(), tmpsifget.add().c_str(),
// tmpsifget.dir(), tmpsifget.res1().c_str(), tmpsifget.res2().c_str(),
// tmpsifget.res3(), tmpsifget.res4(), tmpsifget.res5());
// printfdbg("0x%02x,0x%02x,0x%02x,0x%02x,%ld", myresstr[0], myresstr[1], myresstr[2], myresstr[3],
// myresstr.length());
}
}
void testCompatible1()
{
surTeacherwork::teacherListInfDef savebuf;
surTeacherwork::teacherInfDef *saveinf;
surTeacherwork::teacherListInfNewDef parsebuf;
surTeacherwork::teacherInfNewDef parseinf;
int i;
string packstr;
timerc ctnow;
for (i = 0; i < 10; i++)
{
saveinf = savebuf.add_teacher();
saveinf->set_id(i);
saveinf->set_add("sub_" + to_string(i));
saveinf->set_res7(to_string(i + 2));
}
savebuf.set_buflen(savebuf.teacher_size());
if (!savebuf.SerializeToString(&packstr))
{
printfdbg("");
return;
}
if (!parsebuf.ParseFromString(packstr))
{
printfdbg("");
return;
}
printfdbg("%d, %d, %.3f", parsebuf.buflen(), parsebuf.teacher_size(), ctnow.ints());
for (i = 0; i < parsebuf.teacher_size(); i++)
{
parseinf = parsebuf.teacher(i);
printfdbg("%d,%d,%s,%.2f,%d,%s", parseinf.id(), parseinf.age(), parseinf.add().c_str(), parseinf.res5(),
parseinf.res6(), parseinf.res7().c_str());
}
}
//新版本编码(SerializeToString),老版本解码(ParseFromString)
void testCompatible2()
{
surTeacherwork::teacherListInfNewDef savebuf;
surTeacherwork::teacherInfNewDef *saveinf;
surTeacherwork::teacherListInfDef parsebuf;
surTeacherwork::teacherInfDef parseinf;
int i;
string packstr;
timerc ctnow;
for (i = 0; i < 10; i++)
{
saveinf = savebuf.add_teacher();
saveinf->set_id(i);
saveinf->set_add("ab_" + to_string(i));
saveinf->set_res5(((float)i * 123 - 42) * 0.124);
saveinf->set_res6(i+2);
saveinf->set_res7(to_string(i + 2));
}
savebuf.set_buflen(savebuf.teacher_size());
if (!savebuf.SerializeToString(&packstr))
{
printfdbg("");
return;
}
if (!parsebuf.ParseFromString(packstr))
{
printfdbg("");
return;
}
printfdbg("%d, %d, %.3f", parsebuf.buflen(), parsebuf.teacher_size(), ctnow.ints());
for (i = 0; i < parsebuf.teacher_size(); i++)
{
parseinf = parsebuf.teacher(i);
printfdbg("%d,%d,%s,%s", parseinf.id(), parseinf.age(), parseinf.add().c_str(), parseinf.res7().c_str());
}
}
int main()
{
signal(SIGABRT, dump);
signal(SIGBUS, dump);
signal(SIGSEGV, dump);
testProtoBuff1();
testCompatible1();
testCompatible2();
return 0;
}打印结果:
[2020-11-2 15:11:4.899][dbg][testCompatible1,155]10, 10, 0.000
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]0,0,sub_0,0.00,0,2
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]1,0,sub_1,0.00,0,3
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]2,0,sub_2,0.00,0,4
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]3,0,sub_3,0.00,0,5
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]4,0,sub_4,0.00,0,6
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]5,0,sub_5,0.00,0,7
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]6,0,sub_6,0.00,0,8
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]7,0,sub_7,0.00,0,9
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]8,0,sub_8,0.00,0,10
[2020-11-2 15:11:4.899][dbg][testCompatible1,159]9,0,sub_9,0.00,0,11
[2020-11-2 15:11:4.901][dbg][testCompatible2,196]10, 10, 0.000
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]0,0,ab_0,2
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]1,0,ab_1,3
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]2,0,ab_2,4
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]3,0,ab_3,5
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]4,0,ab_4,6
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]5,0,ab_5,7
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]6,0,ab_6,8
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]7,0,ab_7,9
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]8,0,ab_8,10
[2020-11-2 15:11:4.901][dbg][testCompatible2,200]9,0,ab_9,11