protobuf是什么
ptotobuf是谷歌的语言无关、平台无关可扩展的序列化结构数据格式,例如XML,但是更小、更快、更简单。你只需定义一次结构化数据,然后就可以使用特殊生成的源代码轻松地将结构化数据写入和读取到各种数据流,并且夸语言。
protobuf怎么用
版本及环境
protobuf版本:3.21.12 (3.22及之后版本需要依赖abseil-cpp)
环境:linux
安装
- 下载源码:https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protobuf-cpp-3.21.12.tar.gz
- 解压、编译、安装
- tar zxvf protobuf-cpp-3.21.12.tar.gz
- mkdir build; cd build; cmake .. -DCMAKE_INSTALL_PREIFX=/you/install/dir; make -j
- make install
使用例子
- 目录结构:
examples/
├── CMakeLists.txt
├── protoc
│ └── example.proto
└── src
└── example.cpp
- proto文件(具体可参考:Language Guide (proto 3))
syntax = "proto3"; // 声明使用的语法版本
package example; // 包名
// 消息结构定义,包含一个整数和一个字符串
message Msg {
int32 id = 1;
string name = 2;
}
- cmake文件
cmake_minimum_required(VERSION 3.16)
project(example)
set(CMAKE_CXX_STANDARD 11)
set(PROTOC_BIN /you/install/dir/bin/protoc)
set(PROTO_FILE_DIR /you/project/dir/examples/protoc)
add_custom_command(
OUTPUT ${PROTO_FILE_DIR}/example.pb.h ${PROTO_FILE_DIR}/example.pb.cc
COMMAND ${PROTOC_BIN} -I${PROTO_FILE_DIR} example.proto --cpp_out=${PROTO_FILE_DIR}
DEPENDS ${PROTO_FILE_DIR}/example.proto
)
include_PROTO_FILE_DIRectories(~/tools/include/)
include_PROTO_FILE_DIRectories(~/tools/protobuf/examples/protoc/)
link_PROTO_FILE_DIRectories(~/tools/lib)
add_executable(example src/example.cpp ${PROTO_FILE_DIR}/example.pb.cc)
target_link_libraries(example protobuf)
- 源文件
#include "example.pb.h"
#include <cstdio>
#include <string>
void dump(std::string& data) {
for (size_t i = 0; i < data.size(); i++) {
printf("%02x ", data[i]);
}
printf("\n");
}
int main() {
example::Msg msg;
msg.set_id(1);
msg.set_name("msg");
std::string data;
msg.SerializeToString(&data);
dump(data);
example::Msg msg1;
msg1.ParseFromString(data);
printf("id: %d; name: %s\n", msg1.id(), msg1.name().c_str());
return 0;
}
输出如下:
08 01 12 03 6d 73 67
id: 1; name: msg
protobuf序列化说明
protobuf序列化是TLV
格式即Tag-Length-Value
ID | Name | Used For |
---|---|---|
0 | VARINT | int32, int64, uint32, uint64, sint32, sint64, bool, enum |
1 | I64 | fixed64, sfixed64, double |
2 | LEN | string, bytes, embedded messages, packed repeated fields |
3 | SGROUP | group start (deprecated) |
4 | EGROUP | group end (deprecated) |
5 | I32 | fixed32, sfixed32, float |
Tag = (field_number << 3) | wire_type
08 01 : 08 = (1 << 3) | 0; 01 = 1(id的值)
12 03 6d 73 67: 12 = (2 << 3) | 2; 03 = 3(msg长度); 6d 73 67 = msg(msg的ascii码)
如果深入了解可以搜索:Varint
Zigzag
编解码