1.使用protobuf实现序列化与反序列化
2.Protobuf入门:在linux下编译使用protobuf
3.Protocol Buffer详解(一)
4.Qt6.3 for Android - Protobuf交叉编译
5.windows之google protobuf安装与使用
6.protobuf 详解
使用protobuf实现序列化与反序列化
protobuf是源码用来干嘛的?
protobuf是一种用于对结构数据进行序列化的工具,从而实现数据存储和交换。使用(主要用于网络通信中收发两端进行消息交互。源码所谓的使用“结构数据”是指类似于struct结构体的数据,可用于表示一个网络消息。源码当结构体中存在函数指针类型时,使用通达信机构强弱指标源码直接对其存储或传输相当于是源码“浅拷贝”,而对其序列化后则是使用“深拷贝”。)
序列化:将结构数据或者对象转换成能够用于存储和传输的源码格式。 反序列化:在其他的使用计算环境中,将序列化后的源码数据还原为数据结构和对象。
从“序列化”字面上的使用理解,似乎使用C语言中的源码struct结构体就可以实现序列化的功能:将结构数据填充到定义好的结构体中的对应字段即可,接收方再对结构体进行解析。使用
在单机的源码不同进程间通信时,使用struct结构体这种方法实现“序列化”和“反序列化”的功能问题不大,但是,在网络编程中,即面向网络中不同主机间的通信时,则不能使用struct结构体,原因在于:
(1)跨语言平台,例如发送方是用C语言编写的程序,接收方是用Java语言编写的程序,不同语言的struct结构体定义方式不同,不能直接解析;
(2)struct结构体存在内存对齐和CPU不兼容的问题。
因此,在网络编程中,实现“序列化”和“反序列化”功能需要使用通用的组件,如 Json、XML、protobuf 等。
① 性能高效: 与XML相比,protobuf更小(3 ~ 倍)、更快( ~ 倍)、更为简单。
② 语言无关、平台无关: protobuf支持Java、C++、Python等多种语言,支持多个平台。
③ 扩展性、兼容性强: 只需要使用protobuf对结构数据进行一次描述,即可从各种数据流中读取结构数据,更新数据结构时不会破坏原有的程序。
Protobuf与XML、Json的性能对比:
测试万次序列化:
测试万次反序列化:
protobuf 2 中有三种数据类型限定修饰符:
required表示字段必选,optional表示字段可选,repeated表示一个数组类型。
其中, required 和 optional 已在 proto3 弃用了。
protobuf中常用的数据类型:
下载protobuf压缩包后,解压、配置、编译、安装,即可使用protoc命令查看Linux中是否安装成功:
使用protobuf时,需要先根据应用需求编写 .proto 文件定义消息体格式,例如:
其中,syntax关键字表示使用的protobuf的版本,如不指定则默认使用 "proto2";package关键字表示“包”,生成目标语言文件后对应C++中的namespace命名空间,用于防止不同的消息类型间的命名冲突。
然后使用 protobuf编译器(protoc命令)将编写好的 .proto 文件生成目标语言文件(例如目标语言是C++,则会生成 .cc 和 .h 文件),例如:
其中:
$SRC_DIR表示 .proto文件所在的源目录; $DST_DIR表示生成目标语言代码的目标目录; xxx.proto表示要对哪个.proto文件进行解析; --cpp_out表示生成C++代码。
编译完成后,将会在目标目录中生成xxx.pb.h和xxx.pb.cc文件,将其引入到我们的root explorer源码C++工程中即可实现使用protobuf进行序列化:
在C++源文件中包含xxx.pb.h头文件,在g++编译时链接xxx.pb.cc源文件即可:
在protobuf源码中的/examples 目录下有官方提供的protobuf使用示例:addressbook.proto
参考官方示例实现C++使用protobuf进行序列化和反序列化:
addressbook.proto :生成的addressbook.pb.h 文件内容摘要:add_person.cpp :
输出结果:
三种序列化的方法没有本质上的区别,只是序列化后输出的格式不同,可以供不同的应用场景使用。 序列化的API函数均为const成员函数,因为序列化不会改变类对象的内容,而是将序列化的结果保存到函数入参指定的地址中。
.proto文件中的option选项用于配置protobuf编译后生成目标语言文件中的代码量,可设置为SPEED, CODE_SIZE, LITE_RUNTIME 三种。 默认option选项为 SPEED,常用的选项为 LITE_RUNTIME。
三者的区别在于:
① SPEED(默认值): 表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
② CODE_SIZE: 与SPEED恰恰相反,代码运行效率较低,但是由此生成的代码编译后会占用更少的空间,通常用于资源有限的平台,如Mobile。
③ LITE_RUNTIME: 生成的代码执行效率高,同时生成代码编译后的所占用的空间也非常少。 这是以牺牲Protobuf提供的反射功能为代价的。 因此我们在C++中链接Protobuf库时仅需链接libprotobuf-lite,而非protobuf。
SPEED 和 LITE_RUNTIME相比,在于调试级别上,例如 msg.SerializeToString(&str;); 在 SPEED 模式下会利用反射机制打印出详细字段和字段值,但是 LITE_RUNTIME 则仅仅打印字段值组成的字符串。
因此:可以在调试阶段使用 SPEED 模式,而上线以后提升性能使用 LITE_RUNTIME 模式优化。
最直观的区别是使用三种不同的 option 选项时,编译后产生的 .pb.h 中自定义的类所继承的 protobuf类不同:
① protobuf 将消息里的每个字段进行编码后,再利用TLV或者TV的方式进行数据存储; ② protobuf 对于不同类型的数据会使用不同的编码和存储方式; ③ protobuf 的编码和存储方式是其性能优越、数据体积小的原因。
Protobuf入门:在linux下编译使用protobuf
Google Protocol Buffer(简称Protobuf)是一种由Google公司内部开发的数据标准,用于数据序列化。广泛应用于数据存储和远程过程调用(RPC)系统。它具备语言无关性、平台无关性和可扩展性,支持C++、Java和Python等语言。
编译源码包:从GitHub下载Protobuf的源代码,以2.5.0版本为例。解压后,执行配置编译命令,创建文件。编译后,文件夹中将包含bin、include和lib目录。
测试工程:将include目录下的文件按目录结构和lib/libprotobuf.a复制到测试目录。定义结构化数据Content,包含id(int)、str(string)和opt(可选成员)。使用protoc程序将Mymessage.proto文件编译成目标语言,生成Mymessage.pb.h和Mymessage.pb.cc文件。
将编译后的Mymessage.pb.o文件与Writer.cpp文件一起编译,生成log文件。Reader从log文件读取,反序列化后获得结构化数据。
Protobuf的优点在于高效、紧凑的二进制数据序列化方式,使其适合数据存储和RPC通信。然而,它缺乏复杂概念表示的能力,与XML相比在通用性上仍有不足。XML自解释性使其在文本描述方面优于Protobuf。
高级应用包括嵌套消息、附近门店源码Import Message和动态编译。嵌套消息如Person包含PhoneNumber,用于Person中的phone域。Import Message允许在包中定义公用消息,通过包引入使用。动态编译允许在运行时处理未知的.proto文件。
编写新编译器:利用Google Protocol Buffer源代码中的protoc编译器,可以开发支持其他语言的编译器。通过实现CodeGenerator派生类,实现代码生成功能。
Protobuf的编码方式使用Varint表示数字,节省空间。Varint用一个或多个字节表示数字,值越小字节越少。消息序列化为紧凑的二进制数据流,无需分隔符,可优化大小。
Protocol Buffer详解(一)
Protocol Buffer是一种支持多平台、多语言、可扩展的数据序列化机制,与XML相比,protobuf体积更小、速度更快、使用更简单,支持自定义数据结构。通过protobu编译器,可以生成特定语言的源代码,如C++、Java、Python,protoBuf对主流编程语言都提供了支持,使得序列化和反序列化变得非常方便。
一、Message定义
这里给出一个简单的例子,是一个搜索请求的message格式。
上述例子中fields的种类都是数值型的(string和int),当然也可以指定更加复杂的fields,比如枚举类型enum,或者是嵌套的message类型。
1、分配field编号
上述例子中每个field都被分配了一个编号,这个编号是该field的唯一标识。需要注意的是,标识1-在编码时只占用一个字节,-占用两个字节,因此为了进一步优化程序,对于经常出现的element,建议使用1-作为其唯一标识;对于不经常使用的element,建议使用-。编号的范围是1-2^(-是系统预留的,不要使用)。
2、field类型
message中的field类型包含以下两种(proto3):
(1)singular
(2)repeated:该类型的field可以在message中重复使用(类似于数组),它们的顺序会被保存,通过索引进行检索,数值类型的repeated默认使用packed编码方式。
3、多message结构
在一个proto文件中可以定义多个protobuf。
4、reserved field类型
在开发过程中可能会涉及到对proto文件中message各个fields的修改,可能是更新、删除某个field及其表示,这样可能会导致调用的服务失败。其中一个防止这种问题的方式是,确保你要删除的field的标识(或是名字)是reserved,具体protobuf的编译器会决定未来这个field表示能否被使用。
5、android 见缝插针源码编译结果
对于C++开发者来说,使用protoc编译一个proto文件之后,会生成pb.h和pb.cc两个文件。
二、数值类型
具体proto类型对应生成类中的类型可以参考官方文档。
三、默认值
对于string和byte类型,默认值为空;对于bool类型,默认值是false;对于数值类型,默认值是0;对于枚举类型,默认值是第一个枚举值,默认为0;对于message类型,默认值由编程语言决定;对于repeated field,默认值为空。
四、枚举类型
当采用枚举类型的之后,枚举中的值都是预先定义好的,对于上述例子,我们可以再额外增加一个枚举类型corpus,具体如下。
通常枚举类型的第一个值初始化为0,而且在message中使用枚举类型,必须要给定一个为0的值,而且这个为0的值应该为第一个元素。
也可以给不同的元素以相同的alias,但是需要指定option allow_alias = true;具体如下。
除此之外枚举类型不仅可以定义在message内部,也可以定义在message外部,而且在不同message中可以重用enum。
在更改枚举类型field时,为保证系统运行正常,同样可以指定reserved数字标识和命名。
五、使用其他message类型
1、同文件引用
具体如下:
2、不同文件引用
引用其他proto文件中定义好的message类型,具体如下。
有时我们会对引用的proto文件进行更改,比如将其内容移动到另外一个地方,这样我们就需要对调用方import路径进行更改,当调用方非常多的时候,这种方法是非常低效的,protobuf提供一种机制,我们可以在原有位置提供一个新位置proto文件的“副本”,通过使用import public表示来实现,具体可以参考如下例子。
这时编译器就会在某些固定目录下查询import的proto文件(具体在命令行编译的时候,由-I/—proto_path指定),如果上述路径找不到,编译器会在调用路径进行查找。通常将—proto_path设置为项目的根目录,然后import的时候使用完整的路径名。
3、使用proto2中的message类型
proto2中的枚举类型无法直接使用。
六、嵌套类型
具体如下。
在parent message之外调用嵌套的message可以用如下方式:SearchResponse.Result,嵌套结构可以更加复杂,具体如下:
七、更新message类型
当现有的message已经无法满足现有业务需要,你需要更新你的message类型以支持更复杂的业务,这就涉及到向后兼容的问题了,为保证已有服务不受影响,需要遵守以下的一些规定:
1、不要更改已经存在的fields的数字标识
2、如果添加新的field,利用旧代码序列化得到的老杨ecshop源码message可以使用新的代码进行解析,你需要记住各个元素的默认值。新代码创建的field同样可以由旧代码进行加解析
3、field可以被删除,但是需要保证其对应的数字标识不再被使用,你可以通过加前缀的方式来重新使用这个field name,或者指定数字标识为reserved来避免这种情况
4、int、int、uint、uint、bool这些类型都是互相兼容的,并不会影响前向、后向兼容性
5、sint和sint之间是互相兼容的,但是和其他数字类型是不兼容的
6、string和bytes是互相兼容的,只要使用的是UTF-8编码
7、如果byte包含message的编码版本,则嵌套的message和bytes兼容
8、flexed兼容sfixed,fixed,sfixed
9、enum兼容 int, uint, int, and uint。对于这个值在转化时,不同语言的客户端处理方式会有所不同
感兴趣的小伙伴可以关注公众号:独立团丶
Qt6.3 for Android - Protobuf交叉编译
前言
在开发跨平台应用时,利用Protobuf作为数据传输载体是常见的做法。当项目迁移到Android平台,希望复用C++代码,这时需借助Android NDK的交叉编译工具链进行编译。
交叉编译工具链
为了进行Android平台的交叉编译,首先确保安装了Android SDK、NDK及JDK工具包,这部分内容在前文已有详述,本文不再赘述。
关键点:
1. 选择Clang编译器,确保与Qt for Android程序的编译器相匹配,避免运行时出现问题。
2. 注意Android NDK的不同版本,其交叉编译工具链使用方式有所差异,本文以使用Android NDK 版本为例。
下载Protobuf源码
使用Protobuf 3.0.0版本,通过GitHub链接下载源码。
编写交叉编译脚本
以下示例基于Android NDK 版本,脚本关键部分已注释。更多详细信息可查阅相关文档。
运行脚本后,在指定目录生成适用于不同平台的.so文件、include文件以及protoc工具。
注意事项:
1. 检查编译过程中的日志输出,确保使用了配置的工具链。
2. 执行生成的protoc工具,验证其正确性。注意,生成的protoc为aarch版本,在x Linux环境上无法直接执行。
3. 清理缓存,避免因缓存问题导致配置交叉工具链失败时,切换至本地gcc编译。
对于使用Android NDK r及更早版本的用户,需先生成独立的交叉编译工具链包,再进行配置。使用命令make-standalone-toolchain.sh完成此步骤。
最后,参考相关文档进行详细设置与调试。
windows之google protobuf安装与使用
本文将通过创建一个简单的“地址簿”示例应用程序来展示如何使用 Google Protocol Buffer(简称 Protobuf)。将从以下几点来介绍prototbuf:1.安装 2.定义protobuf消息格式 3.编译protobuf 4.protobuf API 5.读写protobuf消息
1.安装
在Windows下安装protobuf很简单,只需下载protoc-3.4.0-win.zip压缩包然后解压,会看到该bin文件夹下有一个名为protoc.exe的应用程序。这个就是本文要使用的编译器。
2.定义protobuf消息格式
创建一个非常简单的“地址簿”应用程序,可以在文件中读取和写入人员的联系人详细信息。地址簿中的每个人都有姓名,ID,电子邮件地址和联系电话号码。要创建地址簿应用程序,需要从.proto文件开始。.proto文件中的定义很简单:为要序列化的每个数据结构添加消息,然后为消息中的每个字段指定名称和类型。
下面是.proto定义的消息文件addressbook.proto,包含消息的定义以及字段的类型和描述。
syntax = "proto2"; package tutorial; message Person { required string name = 1; required int id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phones = 4; } message AddressBook { repeated Person people = 1; }
每个元素上的“= 1”,“= 2”标记是标识该字段在二进制编码中的唯一“标记”。标记号1-相对于比较大的数字只需要一个字节进行编码,因此作为优化,可以决定将这些标记号用于常用或重复的元素,将标记号和更高的标记号留给不太常用的可选元素。重复字段中的每个元素都需要重新编码标记号,因此重复字段特别适合此优化。
3.编译protobuf
运行protobuf编译器protoc.exe对.proto进行编译,编译命令格式如下:protoc -I = $ SRC_DIR --python_out = $ DST_DIR $ SRC_DIR / addressbook.proto。其中,$ SRC_DIR是源目录(应用程序的源代码所在的位置),$ DST_DIR 是目标目录(希望生成的代码在哪里)。
4.protobuf API
为您的所有消息,枚举和字段以及一些神秘的空类生成特殊描述符,每个消息类型对应一个Python类。可以使用Python类,就好像它将Message基类的每个字段定义为常规字段一样。例如,可以写代码,创建并填充protobuf类的实例,然后将它们写入输出流。
5.读写protobuf消息
使用protobuf类,可以尝试将个人详细信息写入地址簿文件。需要创建并填充protobuf类的实例,然后将它们写入输出流。这是一个程序(文件名为write.py),它从数据文件中读取AddressBook类,根据用户输入添加一个新Person到AddressBook中,然后再将新AddressBook写回文件。
最后会在data.pb文件中产生结果,然后在命令窗口下执行以下命令,会出现输出。到此,关于protobuf的简单使用已经介绍完了,如果想了解更多有关protobuf的使用,请浏览google protocol buffer官网。
protobuf 详解
Protobuf,即Protocol Buffers,是Google公司设计的一种轻量级、高效的结构化数据存储格式,用于结构化数据的序列化。它被广泛应用于数据存储和远程过程调用(RPC)的数据交换,支持语言无关、平台无关、可扩展的序列化结构数据格式。目前主要提供了C++、Java和Python三种语言的API。
Protobuf的优势在于其简洁性和高效性,允许开发者定义数据结构,并以二进制格式进行序列化和反序列化,从而节省了数据传输和存储的空间,同时也加快了数据处理的速度。然而,它也有一些劣势,比如学习曲线陡峭,对于初学者来说可能需要一定时间来熟悉其语法和使用方法。
在安装Protobuf时,protoc(Protocol Compiler)是核心组件,它能将.proto文件编译成不同语言的源代码。为了在Windows环境下安装protoc,首先需从GitHub下载protobuf源码,解压后添加bin目录路径到系统环境变量,然后通过命令行运行protoc查看是否成功安装。
对于Go语言的支持,由于protobuf本身并未直接提供Go语言的API,需要额外安装protoc-gen-go插件来生成Go语言的序列化和反序列化代码。在安装完protobuf后,使用Go1.+版本的命令行安装protoc-gen-go插件。如果需要生成gRPC相关的Go代码,则需要安装protoc-gen-go-grpc插件。
Protobuf的语法涵盖了多种数据类型,包括标量类型、可选类型、重复类型、映射类型以及嵌套的message类型。message成员可以被指定为标量类型,如字符串、整数等,也可以嵌套其他message类型。消息字段可以被标记为可选或重复类型,以适应不同的数据需求。
在.proto文件中定义消息类型时,可以使用默认值来简化序列化过程。默认值在解析数据时如果消息中未包含特定的字段,则将该字段设置为默认值。此外,Protobuf还支持enum(枚举类型)和oneof(互斥字段组)特性,用于定义具有预定义值列表的字段和最多只能设置其中一个字段的字段组。
为了将message与RPC(远程过程调用)结合使用,可以在.proto文件中定义RPC服务接口。通过protobuf编译器protoc,可以生成特定语言的RPC服务代码,包括生成序列化和反序列化的代码以及RPC服务的客户端和服务器代码。
使用protoc编译器将.proto文件编译成目标语言的源代码。编译命令通常会指定输出目录和目标语言,如Go语言。通过设置--go_out参数,可以指定生成的Go代码的基本路径。同时,--go_opt参数可以用来为生成的Go代码指定额外的优化选项。--proto_path参数用于设置Protobuf查找.proto文件的路径。
生成gRPC相关的Go代码需要使用protoc-gen-go-grpc插件,并通过--go-grpc_out参数指定输出目录。这将产生用于gRPC服务的客户端和服务器代码。
要使用protobuf,通常会从源代码下载protobuf,然后通过命令行工具protoc进行编译,从而生成特定语言的序列化和反序列化代码,以及RPC服务代码。对于Go语言,除了需要安装protobuf和protoc-gen-go插件外,还需根据需求安装protoc-gen-go-grpc插件来生成gRPC相关的代码。
七爪源码:学习用于序列化结构化数据的协议缓冲区 (Protobuf) — 第 1 部分
在深入探讨 Protocol Buffers 之前,让我们先了解序列化和反序列化的基本概念。序列化是指将对象转换为线性字节序列以便存储或传输到另一位置的过程。反序列化则是获取存储信息并从中重新创建对象的过程。随着数据的不断增长,序列化和反序列化的数据方法也在不断发展。
CSV(逗号分隔值)是一种易于解析和读取的方法,但存在一些缺点,如必须推断数据类型且不保证。当数据包含逗号且列名存在或不存在时,解析变得困难。关系表定义添加了类型信息,数据是完全类型化的,且可以放入表格中。然而,数据必须是平面的,并且不同数据库的数据定义各不相同。JSON(JavaScript 对象表示法)是一种广泛接受的网络格式,数据可以采用任意形式,易于被多数编程语言读取,并且可通过网络轻松共享。然而,JSON 数据没有模式强制,且 JSON 对象大小较大,因为重复的键。
XML(可扩展标记语言)使用类似于 JSON 的元标记,但带有结束标记。由于它们具有结束标记,因此与 JSON 相比,它们的大小要大得多。
Protocol Buffers(或 Protobuf)是一种语言中立、平台中立的可扩展数据序列化协议,不同于 JSON 或 XML。Protobuf 不适合人类使用,因为序列化数据是编译后的字节,难以供人类阅读。它是 Google 用于序列化结构化数据的机制。
Protocol Buffers 的优点包括易于跨编程语言共享数据。在 .proto 文件上运行 Protocol Buffers 编译器时,编译器会以所选语言生成代码。我们只需使用在 .proto 文件中描述的消息类型,包括获取、设置字段值、将消息序列化到输出流以及从输入流解析消息。
为了更高效地设计 .proto 文件,Google 提供了样式指南,应尽量遵守。标准文件格式包括许可证标题(如有适用)、文件概述、语法、包装、导入(排序)、文件选项和其他内容。在 Protocol Buffers 中,字段标签非常重要。最小标签值可以是 1,最大标签值可以是 2²⁹–1 或 ,,。编号从 1 到 的标签使用 1 个字节,而编号从 到 的标签使用 2 个字节。对经常填充的字段使用 1 到 个标签号。
Protocol Buffers 支持多种字段类型,如布尔型、字符串、字节、重复字段、枚举等。在 Protocol Buffers 中,字段名称不重要,它们仅在编程中引用字段时重要。字段标签很重要,最小标签值可以是 1,最大标签值可以是 ,,。编号从 1 到 的标签使用 1 个字节,而编号从 到 的标签使用 2 个字节。对经常填充的字段使用 1 到 个标签号。
枚举允许我们定义事先知道的一个字段可以取的所有值。默认字段值为布尔型的假、数字的 0、字符串的空字符串、字节的空字节、重复的空列表和枚举的第一个值。我们还可以使用其他消息类型作为字段类型。嵌套类型有助于避免命名冲突并加强局部性。在下一篇文章中,我们将探讨 Protocol Buffers 的高级概念。
protobuf基本使用
Protocol Buffers,简称为 Protobuf,是一种由 Google 提出的高效、灵活的数据序列化方法。它旨在提供数据存储和通信协议的解决方案,比 XML 更小巧、更快速,同时拥有更简单的使用方式。Protocol Buffers 的核心优势在于不需要手动解析结构,提供了一种定义数据结构并自动生成代码进行数据读写的能力。
Protocol Buffers 的使用流程主要包括以下几个步骤:
1. **定义数据结构**:首先,需要创建一个.proto 文件,定义需要序列化的数据结构。这包括字段类型、命名和约束条件。
2. **编译生成代码**:使用 protoc 编译器将 .proto 文件编译为各编程语言对应的源代码文件。编译结果通常包含用于序列化和反序列化数据的函数。
3. **写文件**:使用生成的代码将数据序列化到文件中,通常会提供一个简单的脚本或命令行工具来执行序列化操作。
4. **读文件**:通过反序列化函数将数据从文件中读取到程序中,这一步可以通过另一段生成的代码来完成。
Protocol Buffers 的一个显著优势是,它允许你轻松地更新数据结构而不会破坏已部署的程序。这意味着,即使在数据结构发生变化时,已存在的客户端和服务端代码依然可以继续运行,只需重新编译受影响的代码部分即可。
在实际使用中,Protocol Buffers通常与各种编程语言的第三方库集成,例如 Python、Java、C++ 等,以简化数据交换和存储的实现。它在服务端和客户端通信、数据持久化和配置文件存储等领域有着广泛的应用。
总之,Protocol Buffers 通过提供自动化且高效的数据序列化能力,简化了数据在不同系统和语言之间的交换,使得开发者能够更专注于应用逻辑的实现而非低效的数据处理过程。
在C++中使用Protobuf
ProtoBuf的定义和描述:
Protocol Buffers是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它适用于(数据)通信协议、数据存储等。
Protocol Buffers是一种灵活、高效、自动化的结构数据序列化方法,类似于XML,但比XML更小(3 ~ 倍)、更快( ~ 倍)、更简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松地在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不会破坏由旧数据结构编译的已部署程序。
使用 ProtoBuf教程:
在了解了ProtoBuf的基本概念之后,我们将具体了解如何使用ProtoBuf。
第一步,创建.proto文件,定义数据结构,如下所示:
我们在上例中定义了一个名为Person的消息,语法很简单,message关键字后跟消息名称。之后我们在其中定义了message具有的字段,形式为:
第二步,protoc编译.proto文件生成读写接口:
在.proto文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输。当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、反序列化以及读写。ProtoBuf提供相应的接口代码,可以通过protoc这个编译器来生成相应的接口代码,命令如下:
生成的.h,.cpp文件为person.pb.h,person.pb.cpp,且.h的定义与proto文件的内容相关联:
第三步,编写C++业务代码:
c++业务代码对应的CMakeLists.txt为:
参考链接:
1.1.1模型描述与序列化方法之Protobuf(一):初步使用
protobuf的使用流程相对直接,主要包括安装、编译.proto文件和生成可执行文件。本文将主要关注.proto文件的语法规则。1. 安装与配置
尽管具体版本需要在实际操作中指定,但安装过程通常是下载并执行相应的protobuf可执行文件protoc。2. 编译.proto文件
将编写好的.proto文件通过protoc工具编译,生成工程所需的pb.h和pb.cpp源文件。命令行操作简单,只需指定输入目录、输出目录和要编译的.proto文件名。3. 生成可执行文件
将编译得到的.pb.h和.pb.cpp文件与你的cpp源码一起编译,使用pkg-config提供的protobuf编译参数。4. Proto文件语法详解
Proto文件的基本结构为"字段规则 数据类型 名称 = 域值 [选项 = 选项值];"。字段规则有repeated、optional、required和reserved。例如:repeated string name = 1; 表示可多次出现,包括0次。
optional string name = 1 [default ""]; 表示0次或1次出现,可指定默认值。
required string name = 1; 必须出现1次。
reserved name; 表示废弃,用于迭代更新。
数据类型分为基本类型(如float、uint、string、bool)和复合类型(如message、enum、oneof和map)。message类似C++中的类,而enum则对应枚举。5. 选项与优化
选项如default和packed用于设置默认值和优化编码效率,而deprecated用于标记过时属性。6. 其他
高级功能如extensions、service和options通常不常用,相关内容请参考官方文档。7. 代码接口
编译后的接口结构在官方文档中详细说明,此处不再赘述。