Protobuf安装
Protobuf python接口使用
Protobuf+Msgpack C++接口使用
写一个proto文件,plan.proto
syntax = "proto3";
package robot;
message Path {
uint32 move_direct = 4;
float turn_radius = 5;
float move_distance = 6;
}
message Pose {
float x = 3;
float y = 4;
}
// topic : "planning"
message Planning {
uint64 timestamp = 1;
Pose start_pose = 3;
repeated Path planning_path = 5;
}
生成c++文件
# 单个
protoc plan.proto --cpp_out=./
# 多个文件时
ls . |grep ".proto" |xargs -n 1 protoc -I=. --cpp_out=../proto_cpp
序列化和反序列化
#include "planning.pb.h"
using namespace std;
int mian()
{
// 【1】填充数据
robot::Planning planPB;
// uint64 timestamp = 1;
planPB.set_timestamp(165555555);
// repeated Path planning_path = 5;
robot::Path *p1 = planPB.add_planning_path();
p1->set_move_direct(1);
p1->set_turn_radius(10);
p1->set_move_distance(M_PI/2*10);
planPB.add_planning_path()->set_move_direct(0);
// Pose start_pose = 3;
robot::Pose* pose = planPB.mutable_start_pose();
pose->set_x(1);
pose->set_y(2);
// 【2】pb序列化
string enc;
planPB.SerializeToString(&enc);
// msgpack序列化
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, enc);
cout << sbuf.size() << endl;
// 【3】msgpack序列化
auto handle = msgpack::unpack( // 反序列化
sbuf.data(), sbuf.size()); // 输入二进制数据
auto obj = handle.get(); // 得到反序列化对象
string dec;
obj.convert(dec);// 转换反序列化的数据
// 【4】反序列化
robot::Planning planMsg;
planMsg.ParseFromString(dec);
// 【5】读取数据
int timestamp = planMsg.timestamp();
float x = planMsg.start_pose().x();
for (size_t i = 0; i < planMsg.planning_path_size(); i++)
{
size_t moveDirect = planMsg.planning_path(i).move_direct();
float turnRadius = planMsg.planning_path(i).turn_radius();
float moveDistance = planMsg.planning_path(i).move_distance();
}
}
编译
cmake_minimum_required(VERSION 3.0.2)
project(test)
set(msgpack_INCLUDE_DIRS ./third_party/msgpack_2_1_5/include)
set(protobuf_libs_DIR ./third_party/protobuff_3_13_0/lib)
set(protobuf_INCLUDE_DIRS ./third_party/protobuff_3_13_0/include)
aux_source_directory(./third_party/proto_cpp/ PROTO_CPP)
include_directories(
${msgpack_INCLUDE_DIRS}
${protobuf_INCLUDE_DIRS}
./third_party/include
./third_party/proto_cpp/
)
link_directories(
${protobuf_libs_DIR}
./third_party/lib # lib: 库文件的相对路径
)
add_executable(test mian.cpp ${PROTO_CPP})
target_link_libraries(test
protobuf
)
mkdir build && cd build && cmake .. && make
msgpack
Protobuf 转 Json
C++
#include <fstream>
#include <string>
#include <google/protobuf/util/json_util.h> //proto2json
#include "Planning.pb.h"
bool Proto2Json(const google::protobuf::Message& message, std::string& json)
{
google::protobuf::util::JsonPrintOptions options;
options.add_whitespace = true;
options.always_print_primitive_fields = true;
return MessageToJsonString(message, &json, options).ok();
}
int main()
{
// 【1】填充数据
robot::Planning planPB;
// uint64 timestamp = 1;
planPB.set_timestamp(165555555);
// repeated Path planning_path = 5;
robot::Path *p1 = planPB.add_planning_path();
p1->set_move_direct(1);
p1->set_turn_radius(10);
p1->set_move_distance(M_PI/2*10);
planPB.add_planning_path()->set_move_direct(0);
// Pose start_pose = 3;
robot::Pose* pose = planPB.mutable_start_pose();
pose->set_x(1);
pose->set_y(2);
// 【2】pb序列化
string enc;
planPB.SerializeToString(&enc);
// msgpack序列化
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, enc);
cout << sbuf.size() << endl;
// 【3】msgpack序列化
auto handle = msgpack::unpack( // 反序列化
sbuf.data(), sbuf.size()); // 输入二进制数据
auto obj = handle.get(); // 得到反序列化对象
string dec;
obj.convert(dec);// 转换反序列化的数据
// 【4】反序列化
robot::Planning planMsg;
planMsg.ParseFromString(dec);
// 【5】读取数据
int timestamp = planMsg.timestamp();
float x = planMsg.start_pose().x();
for (size_t i = 0; i < planMsg.planning_path_size(); i++)
{
size_t moveDirect = planMsg.planning_path(i).move_direct();
float turnRadius = planMsg.planning_path(i).turn_radius();
float moveDistance = planMsg.planning_path(i).move_distance();
}
// 【6】转json并存储
std::string msg1savePath = "./msg1.json";
std::ofstream msg1(msg1savePath);
std::string jsonString;
Proto2Json(planMsg, jsonString);
msg1 << std::setw(4) << jsonString << "," << std::endl;
msg1.close();
return 0;
}
python
from google.protobuf import json_format
import Planning_pb2
import json
#【1】填充数据
msg = Planning_pb2.Planning()
path = msg.planning_path.add()
path.move_direct = 0;
path.turn_radius = -2;
path.move_direct = 3;
msg.timestamp = 1666666666333
msg.start_pose.x = 0
msg.start_pose.y = 0
#【2】pb序列化
serializeToString = msg.SerializeToString()
print(serializeToString,type(serializeToString))
# 【3】 反序列化
msg.ParseFromString(serializeToString)
# 【4】取值
for path in msg.planning_path:
print(path.move_direct)
print(msg.timestamp)
# 【5】转json存本地
save_result = open(file = ‘./plan.txt’, mode = 'w')
plan_json = json_format.MessageToDict(msg, preserving_proto_field_name=True)
save_result.write(json.dumps(plan_json))
save_result.close()