C++ protobuf示例

1、linux上安装protobuf3:

1)下载:

https://download.csdn.net/download/liuxiao723846/11584862

2)编译安装:

function check_install_status() {
    if [ $? -ne 0 ]; then
        echo "--!!ERROR"
        exit 1
    fi
}

#install protobuf3
if [ ! -d protobuf-3.6.0 ]; then
    tar -zxf protobuf-3.6.0.tar.gz
    cd protobuf-3.6.0
    ./autogen.sh
    ./autogen.sh && ./configure
        check_install_status
    make -j8
        check_install_status
    make install
        check_install_status
    cd python
    python setup.py install
        check_install_status
    ldconfig
    cd ../../
fi

2、简单示例:

1)person.proto:

package test;

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}

编译,生成C++代码:

$ protoc ./person.proto --cpp_out=./
$ ll
-rw-rw-r--. 1 roo roo  17237 Aug 20 21:19 person.pb.cc
-rw-rw-r--. 1 roo roo  12965 Aug 20 21:19 person.pb.h

2)编写C++业务代码:

#include 
#include 
#include "person.pb.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"


using namespace test;
int main(){
  Person p;
  p.set_name("test");
  p.set_id(1);
  p.set_email("a.iabc.com");

  //------------------将pb二进制信息保存到字符串
  std::string str;
  p.SerializeToString(&str);
  std::cout<

3)编译、运行:

g++ -g -o run person_test.cpp ./person.pb.cc -I. -lprotobuf -pthread -std=c++11
或者
g++ -g -o run person_test.cpp ./person.pb.cc -I. -I/usr/local/protobuf/include -L/usr/local/protobuf/lib -lprotobuf -pthread -std=c++11

4)api说明:

  • p.SerializeToString(&str):将对象p序列化成二进制数据,保存到字符串中;
  • 二进制虽然小,但是可读性差,所以通过google::protobuf::TextFormat::print()方法生成文本数据写入文件;为此需要引入google/protobuf/text_format.h(否则会报‘google::protobuf::TextFormat’ has not been declared错误)、zero_copy_stream_impl.h(否则会报OstreamOutputStream找不到)
  • 除了将pb信息序列化成文本写入文件外,还可以调用google::protobuf::TextFormat::PrintToString(mrlist, &str1); 方法将pb文本信息保存到字符串中;(别忘了加text_format.h头文件)
  • p1.ParseFromString(str);:将字符串中的二进制信息反序列成Person对象;
  • C++版pb的api一般为:pb对象.set_消息属性(value);设置属性值;pb对象.消息属性();获取属性值

3、复杂示例:

1)pb消息结构test.proto:

syntax = "proto2";
package video_stream;

message Item{
	optional string id = 1;
    optional float score = 2;
}
message ModelItems{
    optional string modelName = 1;
    repeated Item itemList = 2;
}
message ModelRecallInfoList{
    repeated ModelItems modelItemsList = 1;
}

message InnerUserPrefResponse {
	optional map user_feed_map = 1;
}

编译:

$ protoc ./test.proto --cpp_out=./
$ ll
-rw-rw-r--. 1 roo roo  55676 Aug 20 23:28 test.pb.cc
-rw-rw-r--. 1 roo roo  32236 Aug 20 23:28 test.pb.h

2)c++业务代码:

#include 
#include 
#include "test.pb.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"

using namespace video_stream;

int main(){

  ModelRecallInfoList mrlist;
  ModelItems* items;
  Item* item;
  
  //model_item1
  items = mrlist.add_modelitemslist();
  items->set_modelname("model_items1");
  //item1
  item = items->add_itemlist(); 
  item->set_id("item1");
  item->set_score(0.9);
  //item2
  item = items->add_itemlist();
  item->set_id("item2");
  item->set_score(1.2);
  
  //model_items2
  items = mrlist.add_modelitemslist();
  items->set_modelname("model_items2");
  //item1
  item = items->add_itemlist();
  item->set_id("model_item2_item1");
  item->set_score(99.9);
  
  std::string str;
  mrlist.SerializeToString(&str);
  //std::cout<

编译、运行:

g++ -g -o run test_main.cpp ./test.pb.cc -I. -lprotobuf -pthread -std=c++11

3)api说明:

pb对象中,子对象需要使用指针;

对于repeated类型:

pb对象.add_属性名() 添加一个子对象的指针

pb对象.属性名_size()返回repeated大小;

pb对象.属性名(i)遍历其中一个子对象;

4、复杂消息示例2:

1)student.proto

package test;

message Address {
  optional string name = 1;
  optional string code = 2;
}
message Student {
  required string name = 1;
  required int32 id = 2;
  repeated string email = 3;
  optional Address ads = 4;
  map other = 5;
}

编译

$ protoc ./student.proto --cpp_out=./
$ ll
-rw-rw-r--. 1 roo roo  55676 Aug 20 23:28 student.pb.cc
-rw-rw-r--. 1 roo roo  32236 Aug 20 23:28 student.pb.h

2)C++业务代码student_test.cpp:

#include 
#include "student.pb.h"
#include "google/protobuf/text_format.h"

using namespace test;

int main(){
  Student p;
  p.set_name("test");
  p.set_id(1);
  p.add_email("a.yxz.com");
  p.add_email("b.abc.com");
  std::string* e = p.add_email();
  *e = "c.iop.com";
  
  Address* ads = p.mutable_ads();
  ads->set_name("taiyuan");
  ads->set_code("0351");

  auto* map = p.mutable_other();  
  (*map)["biye"] = "nuc";
  (*map)["job"] = "abc";

  //============序列化成二进制
  std::string str;
  p.SerializeToString(&str);
  //std::cout< o = p1.other();
  google::protobuf::Map::iterator ite;
  
  std::string others;
  for(ite=o.begin();ite!=o.end();ite++){
    others+=ite->first+":"+ite->second;
  }
  std::cout<<"name:"<

3)说明:

  • 可以看出来,对于子对象、map:设置值得时候一般需要用mutable_属性();获取值一般用属性()
  • 对于pb提供的api,可以在生成的.h文件中查看相应的方法;

补充:对于map的操作:

::google::protobuf::Map< ::std::string, ::std::string >* map = test.mutable_values();
cout << "size: " << f.values_size() << endl;   // size = 0
// add to map
(*map)["a"] = "a1";
(*map)["c"] = "a1";
(*map)["a"] = "a1";
cout << "size: " << f.values_size() << endl;   // size = 3

也可以使用下面:
auto& map = *test.mutable_values();
map["a"] = "a1";

参考:

https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#map-fields

https://www.cnblogs.com/shine-lee/p/10701810.html

http://xcd.blog.techweb.com.cn/archives/173.html

https://www.cnblogs.com/tangxin-blog/p/8314563.html

你可能感兴趣的:(C++)