找回密码
 立即注册
查看: 239|回复: 0

在C++中使用Protobuf

[复制链接]
发表于 2022-6-1 10:24 | 显示全部楼层 |阅读模式
ProtoBuf的定义和描述:
    Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
    Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
    你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
使用 ProtoBuf教程:
对 ProtoBuf 的基本概念有了一定了解之后,我们来看看具体该如何使用 ProtoBuf。
第一步,创建 .proto 文件,定义数据结构,如下所示:
//person.proto
package test;

message Person{
    required string name=1;
    required int32 id=2;
    optional string email=3;
}我们在上例中定义了一个名为 Person的消息,语法很简单,message 关键字后跟上消息名称。之后我们在其中定义了 message 具有的字段,形式为:
message xxx {
  // 字段规则:required -> 字段只能也必须出现 1 次
  // 字段规则:optional -> 字段可出现 0 次或1次
  // 字段规则:repeated -> 字段可出现任意多次(包括 0)
  // 类型:int32、int64、sint32、sint64、string、32-bit ....
  // 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字)
  字段规则 类型 名称 = 字段编号;
}第二步,protoc 编译 .proto 文件生成读写接口:
在.proto 文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输。当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、反序列化以及读写。ProtoBuf 提供相应的接口代码,可以通过 protoc 这个编译器来生成相应的接口代码,命令如下:
// $SRC_DIR: .proto 所在的源目录
// --cpp_out: 生成 c++ 代码
// $DST_DIR: 生成代码的目标目录
// xxx.proto: 要针对哪个 proto 文件生成接口代码

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto

protoc ./person.proto --cpp_out=./生成的.h,.cpp文件为person.pb.h,person.pb.cpp,且.h的定义与proto文件的内容相关联:
namespace test { // 对应 package test;

class Person : public ::google::protobuf::Message { //对应 message Person 且继承自::google::protobuf::Message
public:
  
  inline void set_name(const ::std::string& value); //对应message的字段内容
  inline void set_email(const ::std::string& value);
  inline void set_id(::google::protobuf::int32 value);
  ...
}第三步,编写C++业务代码:
// test_person.cpp
#include <iostream>
#include <fstream>
#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(100);
  p.set_email("a.iabc.com");

  // 将pb二进制信息保存到字符串, 序列化
  std::string str;
  p.SerializeToString(&str);
  std::cout<<"str: ["<<str<<"]"<<std::endl;  

  // 将pb文本信息写入文件
  std::ofstream fw;
  fw.open("./Person.txt", std::ios::out | std::ios::binary);
  google::protobuf::io::OstreamOutputStream *output = new google::protobuf::io::OstreamOutputStream(&fw);
  google::protobuf::TextFormat::Print(p, output);

  delete output;
  fw.close();

  // 将pb文本信息保存到字符串
  std::string str1;
  google::protobuf::TextFormat::PrintToString(p, &str1);
  std::cout<<"str1: ["<<str1<<"]"<<std::endl;

  // 反序列化
  Person p1;
  p1.ParseFromString(str);
  std::cout<<"name:"<<p1.name()<<",email:"<<p1.email()<<",id:"<<p1.id()<<std::endl;

  return 0;
}
c++业务代码对应的CMakeLists.txt为:
cmake_minimum_required(VERSION 2.8.3)
project(protobuf_tutorial)
set(CMAKE_CXX_FLAGS "-std=c++11  ${CMAKE_CXX_FLAGS}")

find_package(Protobuf REQUIRED)
include_directories(
  include
  ${PROTOBUF_INCLUDE_DIRS}
)
add_library(addressbook_protobuf person.pb.cc)
add_executable(test_person test_person.cpp)
target_link_libraries(
    test_person
    addressbook_protobuf
    ${PROTOBUF_LIBRARIES}
)参考链接:
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-26 22:23 , Processed in 0.064297 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表