Protobuf產生於Google,是一種序列化和反序列化協議,具有空間開銷小、解析速度快、兼容性好等優點,非常適合於對性能要求高的RPC(Remote Procedure Call)調用。
1、前期準備
(1)下載protobuf源碼
https://github.com/protocolbuffers/protobuf/releases
(2)下載CMake
2、編譯protobuf
(1)配置CMake
cmake-3.17.1-win64-x64.msi進行默認安裝完成,然後運行cmake-gui.exe。
在"1"處選擇protobuf源碼解壓目錄,後綴爲cmake;
彈出生成器選擇窗口,我們選擇"Visual Studio 15 2017"與"x64",然後點擊"Finish"。
Configure完成後下方提示:"Configuring done"。
然後,我們選擇"Generate",爲protobuf源碼生成VS工程文件。
注意:勾選"protobuf_BUILD_SHARED_LIBS",表示生成動態庫;
Generate完成後下方提示:"Generating done"。
(2)編譯protobuf
在VS中編譯libprotobuf,protoc這2個項目。
生成libprotobufd.lib、libprotocd.lib、protoc.exe。
注意:若需要在Qt+MSVC開發方式下,調用protobuf的lib,那麼需要修改libprotobuf工程屬性,然後再編譯生成lib。
“配置屬性”->“C/C++”->“代碼生成”->運行庫,Debug版選擇“/MDd”,Release版選擇“/MD”,“應用”->"確定"。
參考《QT MSVC版本使用protobuf庫》:https://blog.csdn.net/f1jiaziqing2/article/details/86474311
3、protobuf的簡單使用
我們需要編寫*.proto文件,該文件描述了某結構T中的各數據字段,然後使用protoc.exe編譯*.proto,生成*.cc和*.h文件,也可以生成其他的語言。
我們將*.cc和*.h加入工程中參與編譯,就可以調用這倆文件中方法實現T的序列化和反序列化。
有了這種代碼生成機制,開發人員再也不用吭哧吭哧地編寫那些協議解析的代碼了。
《Protocol Buffers介紹》:https://blog.csdn.net/program_think/article/details/4229773
假設開發一個CS架構的程序,客戶端使用C++,服務器使用Java,那麼我們可以共享一套網絡傳輸協議中涉及到需要串行化的對象proto文件,使用protoc.exe分別將這套proto文件編譯成C++、Java語言版,那麼在服務器和客戶端就可以實現對同一串數據實現反序列化,這種功能正得益於protobuf的跨語言、跨平臺性。
(1)拷貝protobuf頭文件、libprotobufd.lib以及protoc.exe
使用Qt建立一個控制檯工程(略),然後將protobuf頭文件、libprotobufd.lib以及protoc.exe拷貝至工程目錄下,
頭文件都在protobuf-3.11.4\src\google目錄下,我們拷貝google目錄。
(2)新建、編譯proto文件
在工程目錄下,新建一個Account.proto的文本文件,內容如下:
syntax = "proto3";
package IM;
message Account {
//賬號
uint64 ID = 1;
//名字
string name = 2;
//密碼
string password = 3;
}
message User {
Account user = 1;
}
protoc --cpp_out=./ Account.proto
打開Account.pb.h頭文件,發現package表示命名空間,message表示類名,大概如下結構:
namespace IM {
class Account {
// 若干自動生成的代碼
};
class User {
// 若干自動生成的代碼
}
};
(3)Qt工程配置
.pro文件中添加Account.pb.h、Account.pb.cc,添加鏈接libprotobufd.lib庫。
(4)編寫測試代碼
#include <QCoreApplication>
#include <iostream>
#include <fstream>
#include "Account.pb.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
IM::Account account1;
account1.set_id(1);
account1.set_name("windsun");
account1.set_password("123456");
string serializeToStr;
account1.SerializeToString(&serializeToStr);
cout << "Serialization:" << endl;
cout << serializeToStr << endl;
IM::Account account2;
if(!account2.ParseFromString(serializeToStr))
{
cerr << "failed to parse student." << endl;
return -1;
}
cout << "Deserialization:" << endl;
cout << account2.id() << endl;
cout << account2.name() << endl;
cout << account2.password() << endl;
google::protobuf::ShutdownProtobufLibrary();
return a.exec();
}
代碼地址:https://gitee.com/bailiyang/cdemo/tree/master/Protobuf/01AccountTest/
參考鏈接:https://www.cnblogs.com/WindSun/p/12543066.html
===================================================
===================================================
業餘時間不定期更新一些想法、思考文章,歡迎關注,共同探討,沉澱技術!