上一篇介绍了protobuf-c的构建。接下来介绍一下protobuf-c的使用。protobuf最核心的就是proto文件,其次通过protobuf-c编译proto文件生成供c语言调用的库文件和头文件。下面逐一说明一下proto文件的定义、protobuf-c编译以及c语言如何使用protobuf。
成都创新互联专注为客户提供全方位的互联网综合服务,包含不限于网站设计、成都网站建设、云城网络推广、微信小程序定制开发、云城网络营销、云城企业策划、云城品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;成都创新互联为所有大学生创业者提供云城建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com一、proto文件结构
protobuf以消息Message为主要结构,消息中包含具体的字段,字段定义主要以required(必填字段)、optional(可选字段)、repeated(可重复字段)为主,包含了各大编程语言的基本数据类型、引用类型等。具体定义参考如下:
.proto文件:包含了Message结构定义的协议文件,我们需要首先编写.proto文件,然后再生成编程语言对应的源文件。
Message结构:包含了字段的,每一条字段都包含定义声明、数据类型以及字段序号。字段序号是唯一不重复的,序号保证了不同语言和平台的序列化和反序列化字段的字节顺序。
定义声明:
required:声明该字段是必填字段。
optional:声明该字段是可选字段。
repeated:声明该字段是可重复字段,通常用数组表示,也可以是list。
数据类型:protobuf支持的数据类型很全,可参考如下表:
.proto类型 | 描述 | pack | c/c++类型 |
---|---|---|---|
bool | 布尔类型 | pack(1) | bool |
double | 64位浮点类型 | pack(N) | double |
float | 32位浮点类型 | pack(N) | float |
int32 | 32位整数类型 | pack(N) | int |
int64 | 64位整数类型 | pack(N) | __int64 |
uint32 | 无符号32位整数类型 | pack(N) | unsigned int |
uint64 | 无符号64位整数类型 | pack(N) | unsigned __int64 |
sint32 | 32位整数类型,使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。 | pack(N) | int |
sint64 | 64位整数类型 ,使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。 | pack(1) | __int64 |
fixed32 | 32位无符号整数类型 ,总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。 | pack(4) | bool |
fixed64 | 64位无符号整数类型,总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。 | pack(8) | bool |
sfixed32 | 32位整数类型,总是4个字节。 | pack(4) | bool |
sfixed64 | 64位整数类型,总是8个字节。 | pack(8) | bool |
string | 字符串类型 | pack(N) | char*/char[]/std:string |
bytes | 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。 | pack(N) | char*/char[]/std:string |
enum | 用户自定义枚举类型 | pack(N)与 uint32相同 | bool |
message | 用户自定义的消息类型 | pack(N) | struct/class |
N 表示打包的字节并不是固定。而是根据数据的大小或者长度打包。
二、protobuf-c编译proto文件
编译命令:
protoc-c --c_cout=. .proto文件 -lprotobuf-c
举个栗子:
定义消息Message Command(命令),其中包含字段:
指令代码:code 64位长整类型,用于区分指令。
指令类型:type 32位整数类型,说明该指令是查询(0)、读写(1)、调用执行(2)。
调用模块名:module 字符串,调用哪个模块的模块名称。
调用函数名:func 字符串,调用哪个模块的函数名称。
调用函数参数:params 字符串数组,调用函数的参数。
.proto文件如下(Command.proto):
message Command{ required sint64 code = 1; //指令代码 required sint32 type = 2; //指令类型 0 查询 1 读写 2 调用执行 required string module = 3; //调用模块名 required string func = 4; //调用函数名 repeated string params = 5; //函数参数} message CommandResponse{ required sint32 code = 1; //返回代码 0 成功 1 失败 optional string msg = 2; //返回消息 失败消息或成功消息 required sint32 version = 3; //接口版本 repeated Command data = 4; //真正的数据字段}1234567891011121314
执行命令:
protoc-c --c_out=. Command.proto -lprotobuf-c
可以看到生成了Command.pb-c.c和Command.pb-c.h的c语言源文件和头文件。
三、c语言中使用protobuf
接下来尝试调用上面生成的c文件。protobuf-c使用pack和unpack方法做序列化和反序列化操作。
在使用packed之前需要使用__INIT函数创建PB对象,然后为对象中字段逐一赋值。
CommandResponse response=COMMAND_RESPONSE__INIT;
这里需要注意response中包含的Command,也需要使用__INIT函数进行初始化并赋值。
Command command=COMMAND__INIT;
在逐一赋值后,我们需要分配一个buffer用于保存序列化字节,在对buffer分配空间时,可以使用__get_packed_size函数获取PB结构体的大小作为分配空间的大小。
size_t size=command_response__get_packed_size(&response);
接下来使用__pack函数执行序列化操作。
command_response__pack(&response,buf);
反序列化操作可直接使用__unpack函数。得到反序列化后的对象指针,通过指针可直接访问PB中的字段。
CommandResponse *response= command_response__unpack(NULL,size,buf);
在对PB访问完成后,需要通过__free_unpacked来释放反序列化的内存空间。
command_response__free_unpacked(response, NULL);
具体例子可参考protobuf-c的github wiki:https://github.com/protobuf-c/protobuf-c/wiki/Examples
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
网站标题:protobuf-c的使用(二)使用-创新互联
当前URL:http://lswzjz.com/article/deipjc.html