# 清空CMake缓存
# rm -r -Force ${cmake生成的文件名及下面的子目录}
rm -r -Force .\cmake-build-debug\*
第一步,将编译好的protobuf库复制粘贴到项目对应的位置
第二步:编写.proto文件
- 创建.proto文件--------person.proto
- 将protobuf库中的protoc.exe和.proto文件放在同一目录下
# 终端执行,会在同级目录下生成person.pb.cc和person.pb.h文件
./protoc --cpp_out=./ person.proto
- 将生成的源文件和头文件依次放入项目指定的目录,如源文件在src下,头文件在include下
- 编写CMakeLists.txt
# protobuf库需要依赖其子目录下的absl库和utf8_range库
# HINTS后面是absl库在项目中的位置
find_package(absl HINTS ${CMAKE_CURRENT_SOURCE_DIR}/packages/protobuf/lib/cmake CONFIG REQUIRED)
set(ABSEL_LIBARARY absl::log_internal_message absl::log_internal_check_impl absl:: cord_internal absl::cord absl::flat_hash_set absl::status absl::statusor)
# HINTS后面内容同上
find_package(Protobuf HINTS ${CMAKE_CURRENT_SOURCE_DIR}/packages/protobuf REQUIRED)
find_package(utf8_range ${CMAKE_CURRENT_SOURCE_DIR}/packages/protobuf/lib/cmake CONFIG REQUIRED)
set(UTF8RANGE_LIBRARY utf8_range::utf8_validity utf8_range::utf8_range)
#给"通过.proto文件生成的.cc和.h文件存放目录"取一个别名为PROTO_DST_DIR
set(PROTO_DST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/hdrs/public/proto)
#给“.proto文件存放的目录“起一个别名为PROTO_SRC_DIR
set(PROTO_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/resources/proto)
#将所有的.proto文件起一个别名为PROTO_FILES
file(GLOB PROTO_FILES ${PROTO_SRC_DIR}/*.proto)
#通过执行shell命令生成所有.proto文件对应的.cc和.h文件
execute_process(
#shell命令
#假如protoc.exe所在目录在bin目录下 ./packages/protobuf/bin/protoc
#.proto文件所在目录 ./resource/proto/
#生成的.cc和.h文件放置在--cpp_out=的内容
#所有.proto文件
COMMAND ./packages/protobuf/bin/protoc --proto_path=./resource/proto/ --cpp_out=./include/hdrs/public/proto ./resource/proto/*.proto
#在哪个目录下执行这条shell
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
#shell的输出放在OUTPUT_VAR
OUTPUT_VARIABLE OUTPUT_VAR
#RESULT_VAR作判断
RESULT_VARIABLE RESULT_VAR
OUTPUT_QUIET
)
# 1表示有输出,0表示没有
if(RESULT_VAR EQUAL 1)
message("CMake Error: CMakeLists: 53: ${OUTPUT_VAR})
endif()
#比如要将所有生成的.cc文件放在/src/public/proto目录下
#起别名
set(directory ${CMAKE_CURRENT_SOURCE_DIR}/src/public/proto)
#给所有的.cc文件起别名
file(GLOB targets ${PROTO_DST_DIR}/*.pb.cc)
#使用for循环将所有的.cc文件进行复制
foreach(tar ${targets})
# 如果文件存在,就复制到${directory}
if(EXISTS ${tar})
file(COPY ${tar} DESTINATION ${directory})
endif()
endforeach()
#删除原来的.cc文件
file(GLOB RE_FILES ${PROTO_DST_DIR}/*.pb.cc)
#使用循环挨个删除
foreach(FILE ${RE_FILES})
file(REMOVE ${FILE})
endforeach()
#将.pb.h链接到include下,这样在源文件中可以直接声明
include_directors(${CMAKE_CURRENT_SOURCE_DIR}/include ${PROTO_DST_DIR})
file(GLOB PROTO_HDR ${PROTO_DST_DIR}/*.pb.h)
file(GLOB PROTO_SRC ./src/public/proto/*.pb.cc)
add_library(Target main.cpp ${PROTO_SRC} ${PROTO_HDR})
target_link_libraries(Target protobuf::libprotobuf ${ABSEL_LIBARARY} ${UTF8RANGE_LIBRARY})
#以上就是完整的在项目中使用到protobuf库时CMakeLists的内容
protobuf使用示例
//perspn.protobuf文件内容
//指定protobuf版本proto3
syntax = "proto3";
//添加包名
package tutorial;
message Person{
// 三个关键字 repeated、required、option
repeated int32 id = 1;
string name = 2;
optional string email = 3;
}
//main.cpp
#include <iostream>
#include <string>
#include <memory>
//使用上述方法生成的.pb.h文件
#include "person.pb.h"
using namespace std;
int main()
{
tutorial::Person person;
// 添加数据
person.add_id(1);
person.add_id(2);
person.set_name("John");
person.set_email("dadsa.com");
// 序列化
string ser = person.SeroalizeAsString();
// 反序列化
tutorial::Person person1;
// 这是反序列化string类型
// ParseFromArray()可以反序列化char*类型
person1.ParseFromString(ser);
for(int i = 0;i < person1.id_size();i++)
{
cout << person1.id(i) << endl;
}
cout << person1.name() << endl;
cout << person1.email() << endl;
return 0;
}