一. 描述
ProtoBuf (Google Protocol Buffer) 是由 google 公司用于数据交换的序列结构化数据格式,具有跨平台、跨语言、可扩展特性。
二. 使用
1. 安装
sudo apt-get install protobuf-compiler
2. 编写 proto 文件
自己写一个 test.proto
文件
syntax = "proto2" ; //表明使用protobuf的编译器版本为v2,目前最新的版本为v3
package apollo.common ; //声明了一个包名,用来防止不同的消息类型命名冲突,类似于 namespace
/*****************************
导入了一个外部proto文件中的定义,
类似于C++中的 include 只能import当前目录及当前目录的子目录中的proto文件
*****************************/
//import "src/help.proto" ;
message Info
{
//name 是字段名,1 是字段的标识号,在消息定义中,每个字段都有唯一的一个数字标识号,
//这些标识号是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改变。
//标识号的范围在:1 ~ 229 - 1,其中[19000-19999]为Protobuf预留,不能使用。
optional string name = 1 ;
optional int32 age = 2 ;
optional int32 xxx = 3 ; //xxx 代表任意字段名称,为api 举例方便
}
message VehicleSignal {
enum TurnSignal {
TURN_NONE = 0 ;
TURN_LEFT = 1 ;
TURN_RIGHT = 2 ;
};
optional TurnSignal turn_signal = 1 ;
// lights enable command
optional bool high_beam = 2 ;
optional bool low_beam = 3 ;
optional bool horn = 4 ;
optional bool emergency_light = 5 ;
oneof task_config {
int32 aaa = 6;
int32 bbb = 7;
}
}
3. 编译
protoc -I=./ --cpp_out=./ test.proto
注意: test.proto
前面有个空格是指定 .h
和 .c
文件输出目录
如下:
seivl@seivl-Default-string:~/me/代码/third_part_library/proto_test/$ protoc -I=./ --cpp_out=./ test.proto
seivl@seivl-Default-string:~/me/代码/third_part_library/proto_test/$ tree -L 1
.
├── test.pb.cc
├── test.pb.h
└── test.proto
0 directories, 3 files
4. 修改 CMakeLists,使用
把 test.pb.h
文件和 test.pb.cc
文件,放到 CMakeLists
中,然后添加:
cmake_minimum_required(VERSION 2.8.9)
project(test_proto)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Protobuf REQUIRED)
if (Protobuf_FOUND) # 需要特别注意Protobuf_FOUND的大小写
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
else (Protobuf_FOUND)
MESSAGE(FATAL_ERROR "PROTOBUF NOT FOUNED")
endif (Protobuf_FOUND)
set(ALL_SOURCES
# modules/common
${CMAKE_CURRENT_SOURCE_DIR}/include/test.pb.cc
)
set(ALL_HEADERS
# modules/common
${CMAKE_CURRENT_SOURCE_DIR}/include/test.pb.h
)
file(GLOB SOURCES "src/*.cpp")
link_directories(${PROTOBUF_LIBRARIES})
add_executable(test_proto ${SOURCES} ${ALL_SOURCES} ${ALL_HEADERS})
target_link_libraries(test_proto ${PROTOBUF_LIBRARY_DEBUG})
5. 代码
#include <stdio.h>
#include <iostream>
#include <string>
#include "test.pb.h"
using namespace std;
// using namespace apollo::common;
int main ( int argc, char * argv[])
{
apollo::common::Info* pinfo = new apollo::common::Info ();
pinfo->set_name("deng");
pinfo->set_age(120);
cout << "info.name = " << pinfo-> name() << ", age = " << pinfo-> age() << endl;
delete pinfo;
apollo::common::VehicleSignal* psignal = new apollo::common::VehicleSignal();
psignal->set_turn_signal(apollo::common::VehicleSignal::TURN_RIGHT);
cout << "psignal.turn_signal = " << psignal->turn_signal() << endl;
psignal->set_aaa(111);
psignal->set_bbb(222);
cout << "psignal.aaa = " << psignal->aaa() << ",psignal.bbb = " << psignal->bbb() << endl;
return 0 ;
}
- Oneof 特性
设置 oneof 字段会自动清除其它 oneof 成员字段的值,
所以设置多个字段之后,只有最后一次设置的字段会有值,结果如下,也很好理解了。
6. 结果
seivl@seivl-Default-string:~/me/代码/third_part_library/proto_test/test_proto/bu
ild$ make
Scanning dependencies of target test_proto
[ 9%] Building CXX object CMakeFiles/test_proto.dir/src/main.cpp.o
[ 18%] Linking CXX executable test_proto
[100%] Built target test_proto
seivl@seivl-Default-string:~/me/代码/third_part_library/proto_test/test_proto/bu
ild$ ./test_proto
info.name = deng, age = 120
psignal.turn_signal = 2
psignal.aaa = 0,psignal.bbb = 222