找回密码
 立即注册
查看: 218|回复: 1

Protobuf C++的简单使用-带例程

[复制链接]
发表于 2022-9-6 13:54 | 显示全部楼层 |阅读模式
Protobuf C++的简单使用-带例程

[toc]
Protobuf简介

以C++而言,简单的说就是可以将多种类型的数据如vector、map序列化至协议缓存区中,协议缓冲区的数据可以用来进程之间通信,也可以以二进制形式直接写到硬盘中,实现不占用内存的目的。Protobuf读写速度快,一般都在ms级别,是目前最高效的序列化工具。 protobuf由一些基础的消息类型组成更高级的数据类型,这里以一个包含Eigen的结构体在硬盘中的读写为例。
syntax = "proto3";

package proto;

message Vector3d {
  double x = 1;
  double y = 2;
  double z = 3;
}

message RangeData {
  repeated int32 point_x = 1;
  repeated int32 point_y = 2;
  Vector3d local_pose = 3;
  int64 time_stamp = 4;
}其中repeated声明了一个类似于std::vector的数据,可连续存储,以上消息在C++对应了一个结构体:
struct RangeData {
  RangeData();
  explicit RangeData(const proto::RangeData& range_data_proto);
  std::vector<double> points_x;
  std::vector<double> points_y;
  Eigen::Vector3d local_pose;
  int64_t time_stamp;
};
其中explicit RangeData(const proto::RangeData& range_data)输入参数为proto::RangeData,即是前面所定义的消息类型message RangeData,对于此结构体,我们需要写一个以proto作为输入的构造函数,和将当前数据输出为Proto的输出函数ToProto,两个函数实现如下:
// 基于proto的构造函数
Eigen::Vector3d ToEigen(const proto::Vector3d& proto) {
  return Eigen::Vector3d(proto.x(), proto.y(), proto.z());
}

RangeData::RangeData(const proto::RangeData& range_data_proto) {
  this->time_stamp = range_data_proto.time_stamp();
  this->local_pose = ToEigen(range_data_proto.local_pose());
  for(const auto& point_x : range_data_proto.points_x()) {
    this->points_x.emplace_back(point_x);
  }
  for(const auto& point_y : range_data_proto.points_y()) {
    this->points_y.emplace_back(point_y);
  }
}

// 将range_data输出为proto
proto::Vector3d ToProto(const Eigen::Vector3d& vector) {
  proto::Vector3d proto;
  proto.set_x(vector.x());
  proto.set_y(vector.y());
  proto.set_z(vector.z());
  return proto;
}

proto::RangeData ToProto(const RangeData& range_data) {
  proto::RangeData proto;
  *proto.mutable_points_x() = {range_data.points_x.begin(), range_data.points_x.end()};
  *proto.mutable_points_y() = {range_data.points_y.begin(), range_data.points_y.end()};
  *proto.mutable_local_pose() = ToProto(range_data.local_pose);
  proto.set_time_stamp(range_data.time_stamp);
  return proto;
}
以上就实现了基于proto的读写,得到了协议缓冲区数据proto::RangeData,进一步可以将此函数以二进制形式写到硬盘中,这部分是参考cartograpth代码,在本文例程的proto_io.h proto_io.cc中实现。
本文例程

protobuf需要安装google的protobuf库,安装参考 https://www.lmlphp.com/user/56/article/item/6067/
同时可以将protobuf用cmake生成动态.so库,需要的时候直接链接就好,本例程的Proto cmake:
# 查找 protobuf
find_package(Protobuf REQUIRED)

# 编译 proto 为 .cpp 和 .h
FILE(GLOB PROTO_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
message(STATUS ${PROTO_FILES})

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${PROTO_FILES})
message("PROTO_SRCS = ${PROTO_SRCS}")
message("PROTO_HDRS = ${PROTO_HDRS}")

add_library(proto STATIC ${PROTO_SRCS} ${PROTO_HDRS})

target_link_libraries(proto ${Protobuf_LIBRARIES})

target_include_directories(proto
        PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
        PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
        PUBLIC ${PROTOBUF_INCLUDE_DIRS})在主程序中将其作为子模块,主程序的cmake:
cmake_minimum_required(VERSION 3.2)

project(proto_demo)

find_package(Eigen3 REQUIRED)
set(BOOST_COMPONENTS iostreams)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})

include_directories(include
                    build # 为了更方便的使用proto的代码提示
                    ${EIGEN3_INCLUDE_DIR}
                    ${Boost_INCLUDE_DIRS})

add_subdirectory(proto)
add_library(${PROJECT_NAME}
                        src/grid_2d.cc
            src/submap_2d.cc
                        src/proto_io.cc
                        )
target_link_libraries(${PROJECT_NAME} proto ${Boost_LIBRARIES})
add_executable(demo app/demo.cc)
target_link_libraries(demo ${PROJECT_NAME})具体例程如下:
git clone https://github.com/hipforth/proto_demo.git
cd proto_demo && mkdir build && cd build
cmake .. && make
./demo demo.bindemo.bin即为写入的protobuf二进制格式数据
发表于 2022-9-6 13:59 | 显示全部楼层
您好,可以要背景猫的照片吗,谢谢
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-25 04:06 , Processed in 0.088957 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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