protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
Caffe采用的是C++和Python的API。
作用
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
工作原理
proto文件定义格式如下
package caffe;
// Specifies the shape (dimensions) of a Blob.
message BlobShape {
repeated int64 dim = 1 [packed = true];
}
该代码经protobuf编译过后,会产生对应的.h文件和.cc文件。.h文件定义了在命名空间caffe下的BlobShape类,.cc文件实现了BlobShape类的参数各种操作方法,包括设置变量值、清除变量值等。
proto文件语法
proto语法很简单,以caffe.proto文件为例介绍:
package caffe; //package会生成namespace
message BlobProto { //message会生成class
optional BlobShape shape = 7;//optional意味着Blob可以有一个或者没有这个参数
repeated float data = 5 [packed = true];//repeated意味着float类型的data和diff可以重复任意次
repeated float diff = 6 [packed = true];
repeated double double_data = 8 [packed = true];
repeated double double_diff = 9 [packed = true];
// 4D dimensions -- deprecated. Use "shape" instead.
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
}
- Required: 表示是一个必须字段
- Optional:表示是一个可选字段
- Repeated:表示该字段可以包含0~N个元素。
proto支持的数据类型
使用方法
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
- protoc为Protocol Buffer提供的命令行编译工具。
- —proto_path等同于-I选项,主要用于指定待编译的.proto消息定义文件所在的目录,该选项可以被同时指定多个。
- –cpp_out选项表示生成C++代码,–java_out表示生成Java代码,–python_out则表示生成Python代码,其后的目录为生成后的代码所存放的目录。
- path/to/file.proto表示待编译的消息定义文件。
注:对于C++而言,通过Protocol Buffer编译工具,可以将每个.proto文件生成出一对.h和.cc的C++代码文件。生成后的文件可以直接加载到应用程序所在的工程项目中。
举例
步骤1
定义一个proto文件,名字叫test.proto
package august;
enum ClassType{
DATAMINING = 0;
COMPUTERVISION = 1;
}
message Class{
required int32 id = 1;
optional ClassType name = 2 [default = COMPUTERVISION];
}
这个proto文件,定义了命名空间august,在该空间中定义了一个枚举类型ClassType,和一个类Class。
步骤2
使用protobuf编译该文件:
protoc -I=. --cpp_out=. test.proto
通过该命令会生成test.pb.h和test..pb.cc文件。
步骤3
编写C++文件来测试生成.h和.cc文件,该文件名称test_class.cpp。
#include <iostream>
#include <fstream>
#include "test.pb.h" //添加proto生成的.h文件
int main(int argc, char* argv[]){
dataguru::Class cls;//定义一个Class类型的变量cls
cls.set_id(100);//proto文件中class类有int32类型的变量id,通过set_id来赋值
cls.set_name(dataguru::DATAMINING);//class类还有ClassType类型的name,用ClassType枚举类型的值DATAMINING赋值。
std::cout<<"Class::id is "<<cls.id()<<std::endl;
switch(cls.name()){
case 0:
std::cout<<"Class::name is "<<"DATAMINING"<<std::endl;
break;
case 1:
std::cout<<"Class::name is "<<"COMPUTERVISION"<<std::endl;
break;
}
return 0;
}
设置一个值时使用:”set_”+”变量名”
步骤4
编译该test_class.cpp文件
gcc -o test_class test_class.cpp test.pb.cc -lprotobuf -lstdc++
注意:
- 必须连同test.pb.cc一起编译,因为test.pb.cc此时还未编译。
- -lprotobuf :链接protobuf库。