protobuf的使用
protobuf
官网:
https://developers.google.cn/protocol-buffers/
https://github.com/protocolbuffers/protobuf/releases
Linux下下载
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protobuf-all-3.14.0.tar.gz
安装
tar -zxvf protobuf-all-3.14.0.tar.gz
./configure --prefix=/usr/local/protobuf
make
make check
sudo make install
编写addressbook.proto
文件
syntax = "proto2";
package lm;
message helloworld
{
required int32 id = 1; // ID
required string str = 2; // str
optional int32 opt = 3; //optional field
}
写好 proto 文件之后就可以用 Protobuf 编译器将该文件编译成目标语言了。本例中我们将使用 C++。
protoc -I=. --cpp_out=. ./addressbook.proto
命令将生成两个文件:
addressbook.pb.h
: 类声明的头文件addressbook.pb.cc
:类实现
编写 writer 和 Reader
probufwriter.cpp
#include "addressbook.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
int main(void)
{
lm::helloworld msg1;
msg1.set_id(101);
msg1.set_str("hello");
// Write the new address book back to disk.
fstream output("./log", ios::out | ios::trunc | ios::binary);
if (!msg1.SerializeToOstream(&output)) {
cerr << "Failed to write msg." << endl;
return -1;
}
return 0;
}
probufread.cpp
#include "addressbook.pb.h"
#include <iostream>
#include <fstream>
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);
}
g++ -std=c++11 -g -Wall addressbook.pb.cc probufwriter.cpp -o s -lprotobuf -I /include -lpthread
g++ -std=c++11 -g -Wall addressbook.pb.cc probufread.cpp -o c -lprotobuf -I /include -lpthread
luni@ubuntu:~/Project/src$ ./s
luni@ubuntu:~/Project/src$ ./c
101
hello
编译时需要加上-lpthread
否则运行程序会报错,报错信息如下
[libprotobuf FATAL google/protobuf/generated_message_util.cc:783] CHECK failed: (scc->visit_status.load(std::memory_order_relaxed)) == (SCCInfoBase::kRunning):
terminate called after throwing an instance of ‘google::protobuf::FatalException’
what(): CHECK failed: (scc->visit_status.load(std::memory_order_relaxed)) == (SCCInfoBase::kRunning):
例子2:
news.proto
syntax = "proto2";
package test.proto;
message NewsHead {
optional sint32 channel_id = 1;
}
message NewsRecord {
optional bytes author = 1;
optional bytes title = 2;
optional bytes summary = 3;
optional bytes source = 4;
optional sint32 update_date = 5;
optional sint32 update_time = 6;
optional sint32 publish_date = 7;
optional sint32 publish_time = 8;
}
message NewsStruct {
required NewsHead head = 1;
repeated NewsRecord record = 2;
}
protoc -I=. --cpp_out=. ./news.proto
demo.cpp
#include "news.pb.h"
#include <iostream>
using namespace std;
using namespace test::proto;
void parse_news(NewsStruct *news) {
const NewsHead &head = news->head();
cout << "[head] channel_id: " << head.channel_id() << endl;
int recordNum = news->record_size();
for(int i = 0; i < recordNum; ++i) {
const NewsRecord &record = news->record(i);
cout << "[record " << i << "] title: " << record.title() << endl;
}
}
void generate_news(NewsStruct *news) {
NewsHead *head = news->mutable_head();
head->set_channel_id(250);
for(int i = 0; i < 5; ++i) {
NewsRecord *record = news->add_record();
record->set_title("你好,世界");
}
}
int main() {
NewsStruct news;
generate_news(&news);
parse_news(&news);
}