protobuf C++使用实例

栏目: 服务器 · 发布时间: 7年前

内容简介:由于项目中使用protobuf,因此本文学习总结protobuf-C++的基本使用,试验环境为centos7-x64.什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍:Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

由于项目中使用protobuf,因此本文学习总结protobuf-C++的基本使用,试验环境为centos7-x64.

protobuf简介

什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍:

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、 JavaPython 三种语言的 API。

protobuf安装

protobuf clone或者下载后,执行:

./autogen.sh

./configure --prefix=/usr/local/protobuf

make

make check

make install

以下命令需要root权限,如不是root登录需要sudo

vim /etc/profile

添加

export PATH=$PATH:/usr/local/protobuf/bin/

export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/

保存执行

source /etc/profile

当然也可以直接执行两次export语句。

此时我们执行protoc --version就可以看到protobuf的版本信息:

[root@centos-linux-7 protobuf]# protoc --version

libprotoc 3.6.0

如果提示命令protoc不存在,则在~/.profile中添加上面两行代码。

配置动态链接库路径

vi /etc/ld.so.conf

插入:

/usr/local/protobuf/lib

执行:

ldconfig

为什么要使用protobuf

假如我们要实现write将把一个结构化数据写入磁盘,以便其他人来读取。如果我们不使用 Protobuf,一个可能的方法是将数据转换为字符串,然后将字符串写入磁盘。转换为字符串的方法可以使用 sprintf(),这非常简单。数字 123 可以变成字符串”123”。

这样做似乎没有什么不妥,但是仔细考虑一下就会发现,这样的做法对写 read 的那个人的要求比较高。比如”123”可以是单个数字 123,但也可以是三个数字 1,2 和 3,等等。这么说来,我们还必须让 write 定义一种分隔符一样的字符,以便 read可以正确读取。但分隔符也许还会引起其他的什么问题。最后我们发现一个简单的 Helloworld 也需要写许多处理消息格式的代码。

如果使用 Protobuf,那么这些细节就可以不需要应用程序来考虑了。

使用 Protobuf,write的工作很简单,需要处理的结构化数据由 .proto 文件描述,并定义在 lm.helloworld.pb.h 中。对于本例,类名为 lm::helloworld。Writer 需要 include 该头文件,然后便可以使用这个类了。

当我们需要将该结构化数据保存到磁盘上时,类 lm::helloworld 已经提供相应的方法来把一个复杂的数据变成一个字节序列,我们可以将这个字节序列写入磁盘。

对于想要读取这个数据的程序来说,也只需要使用类 lm::helloworld 的相应反序列化方法来将这个字节序列重新转换会结构化数据。这同我们开始时那个“123”的想法类似,不过 Protobuf 想的远远比我们那个粗糙的字符串转换要全面,因此,我们不如放心将这类事情交给 Protobuf 吧。

msg.proto

syntax="proto3";
package lm; 
message helloworld 
{ 
    int32     id = 1;  // ID   
    string    str = 2;  // str  
    int32     opt = 3;  //optional field 
}

写好 proto 文件之后就可以用 Protobuf 编译器将该文件编译成目标语言了。本例中我们将使用 C++。

使用如下命令可以生成我们所需要的.cc与.h

protoc --cpp_out=. ./msg.proto

执行上述命令将生成msg.pb.cc与msg.pb.h,执行时需要在文件msg.proto所在的目录下执行。

write.cc
#include "msg.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
 
int main(void) 
{ 
 
    lm::helloworld msg1; 
    msg1.set_id(101); 
    msg1.set_str("hello"); 
    fstream output("./log", ios::out | ios::trunc | ios::binary); 
 
    if (!msg1.SerializeToOstream(&output)) { 
        cerr << "Failed to write msg." << endl; 
        return -1; 
    }        
    return 0; 
}

Msg1 是一个 helloworld 类的对象,set_id() 用来设置 id 的值。SerializeToOstream 将对象序列化后写入一个 fstream 流。

read.cc

#include "msg.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
 
void ListMsg(const lm::helloworld & msg) {  
    cout << msg.id() << endl; 
    cout << msg.str() << endl; 
} 
 
int main(int argc, char* argv[]) { 
 
    lm::helloworld msg1; 
 
    { 
        fstream input("./log", ios::in | ios::binary); 
        if (!msg1.ParseFromIstream(&input)) { 
            cerr << "Failed to parse address book." << endl; 
            return -1; 
        }       
    } 
 
    ListMsg(msg1); 
}

对应的Makefile:

all: write read
 
clean:
    @rm -f write read msg.*.cc msg.*.h *.o  log
 
write: msg.pb.cc write.cc
    g++ -std=c++11  msg.pb.cc write.cc -o write  `pkg-config --cflags --libs protobuf`
 
read: msg.pb.cc read.cc
    g++ -std=c++11  msg.pb.cc read.cc -o read  `pkg-config --cflags --libs protobuf`

msg.pb.cc msg.pb.h :msg.proto
    protoc --cpp_out=. ./msg.proto

执行make之后,生成可执行文件write 和read.

执行结果:

[root@centos-linux-7 protobuf]# make

make: 对“all”无需做任何事。

[root@centos-linux-7 protobuf]# ./write

[root@centos-linux-7 protobuf]# ./read

101

hello

常见错误及处理:

1.error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

#error This file requires compiler and library support for the

这个错误出现的话需要在Makefile中指定=std=c++11

更多C++的例子可以参考官方文档: protobuf cpptutorial

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hacking

Hacking

Jon Erickson / No Starch Press / 2008-2-4 / USD 49.95

While other books merely show how to run existing exploits, Hacking: The Art of Exploitation broke ground as the first book to explain how hacking and software exploits work and how readers could deve......一起来看看 《Hacking》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具