一、protobuf的下载安装
1、protobuf的下载:这里。此处下载的是protobuf-cpp-3.9.1.tar.gz。
2、安装准备:安装protobuf前确保以下软件都已经被安装。方法也很简单yum -y install XXXX即可。
autoconf
automake
libtool
make
g++
unzip
注:值得注意的是我们要将g++设为默认使用C++11,可以在终端执行:
alias g++='g++ -std=c++11'
但是切记:这个只是临时生效的,永久有效的方法是将上述语句写入/root/.bashrc 文件中。
vim /root/.bashrc
添加:alias g++='g++ -std=c++11'
3、安装protobuf:
执行如下命令,安装时间有点长,耐心等待(可以写成自动化脚本,就无需一步一步执行):
./configure
make #时间有点长
make check #时间有点长
sudo make install
sudo ldconfig # refresh shared library cache.
这时一般来说
libprotobuf库在/usr/local/lib路径下;protoc一般在/usr/local/bin路径下 。如下:
4、配置环境变量
主要是完善PATH和PKG_CONFIG_PATH等环境变量
$ sudo vim /etc/profile
添加
export PATH=$PATH:/usr/local/bin/
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ #这个参数是必须的
#我添加了这些,感觉有些没有也可以。
export PATH=$PATH:/usr/local/bin
export PATH=$PATH:/usr/local/include
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
保存生效
source /etc/profile
注:(1)保存生效的语句需要在每个终端都执行一遍才可以生效;
(2)通过echo $PATH / echo $PKG_CONFIG_PATH的方法验证配置在本终端有没有生效。
(3)上述配置中PKG_CONFIG_PATH是必须的(当然其他可能也是必须的),如果没有在编译的时候会报如下错误:
这里的protobuf.pc存了protobuf相关的头文件和库相关的信息,这些信息都是编译的时候要用到的。这里是因为我们使用了pkg-config来方便引用了的,关于pkg-config参见 这里。
5、配置动态路径
sudo vim /etc/ld.so.conf
追加
/usr/local/lib
然后以root权限更新动态库路径
ldconfig
6、验证有没有安装成功
执行:
protoc --version
能够显示相应版本信息就说明安装成功。
二、使用举例
1、person.proto文件:
syntax = "proto3";#指定使用proto3
package tencent; #命名空间
message Person
{
string name = 1;
uint32 age = 2;
uint64 phnum = 3;
}
注意:proto3和proto2的区别还是蛮大的,此处没有了proto2中常见的optional、required之类的修饰。
2、编译.proto文件。执行如下指令对.proto文件按照c++的形式进行编译,此时会生成相对应的pb.cc文件和pb.h文件。
#推荐这种顺序
protoc person.proto --cpp_out=./ #末尾的'./'表示生成的cc、h文件存放在当前目录(可调整)。
protoc person.proto --python_out=./ #我们也可以生成python之类的编译文件
#当然调换一下参数顺序也是一样的
protoc --cpp_out=./ person.proto
protoc --python_out=./ person.proto
#另外也是可以一次性编很多文件的,如下:
protoc com.tencent.*.proto --python_out=.
protoc com.tencent.epc.qidian.cc*.proto --python_out=.
效果如下:
3、python对序列化的字串反序列化为protobuf结构
注:其中用到的im_msg_body_pb2就是im_msg_body.proto文件经过编译后生成的python库文件。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import im_msg_body_pb2
row_msg_body = b"\n\271\001\n!\010\000\020\223\203\321\363\005\030\343\337\232\334\007 \000(\n0\0008\206\001@\002J\006\345\256\213\344\275\223\022^\312\001[\nY\010\003\022\004\010\000\020\001(\0030\242\333\255\311\005H\225\340\215\320\n\212\001\017861684676539011\352\001.webim_2852155980_861684676539011_1584676769010\0224\n2\n0\345\275\223\346\227\266\347\273\231\346\210\221\344\273\213\347\273\215\347\232\204\346\227\266\345\200\231\350\257\264\344\270\200\346\254\241\346\200\247\351\200\200\345\256\214\345\225\212";
print("----------实例结构对象,对原生字串反序列化-----------")
msgbody = im_msg_body_pb2.MsgBody()
msgbody.ParseFromString(row_msg_body)
print(msgbody)
print("---------------母结构赋值子结构----------------------")
rich_text = im_msg_body_pb2.RichText()
rich_text = msgbody.rich_text;
print(rich_text)
print("----------取repeated对象(Elem为repeated)------------")
elem = im_msg_body_pb2.Elem();
elem = msgbody.rich_text.elems[1]
print(elem)
print("-----------下面打印的就是汉字了----------------")
text = im_msg_body_pb2.Text();
text = msgbody.rich_text.elems[1].text
print(text.str)
4、数据读写之write.cc写数据到本地硬盘
#include#include#include "person.pb.h"
using namespace std;
using namespace tencent;
int main()
{
Person p1;
p1.set_name("shuozhuo");
p1.set_age(22);
p1.set_phnum(17367078333);
fstream output("./log",ios::out | ios::trunc | ios::binary);
if (!p1.SerializeToOstream(&output)){
cerr << "Failed to write msg."<
执行如下语句进行编译,生成可执行文件write,并执行之:
g++ person.pb.h person.pb.cc write.cc -o write `pkg-config --cflags --libs protobuf` -lpthread
注意:(1)上述指令中的“`”并不是单引号,而是键盘上按键“1”左边的那个按键对应的符号。
(2)关于pkg_config还是值得继续学习的。
(3)编译 时添加 -lprotobuf库到编译选项中。
5、编写read.cc从本地读取数据
#include#include#include "person.pb.h"
using namespace std;
using namespace tencent;
void PrintInfo(const Person &p1){
cout << "The information is:" << endl;
cout << " name:" << p1.name() <
编译语句如下,完成后生成可执行文件read:
g++ person.pb.h person.pb.cc read.cc -o read `pkg-config --cflags --libs protobuf` -lpthread
执行read,效果如下:
三、protobuf学习
更多学习,参见 protobuf使用手册