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);
}
posted @ 2020-12-11 11:11  不知云深处  阅读(958)  评论(1编辑  收藏  举报