市面上大多博客没介绍如何组建多目录,多proto的项目经验,如果本博客经验如果能帮到你,那真是太好了
本次代码生成C++代码,测试用例采用gtest进行搭建,工程目录如下:
hobby.proto
位于protocol/hobby下,内容入下:
syntax = "proto3";
enum Hobby {
kGame = 0;
kSwim = 1;
kFootball = 2;
kBasketball = 3;
kTableTennis = 4;
kImAWaste = 5;
}
我在basic_data.proto
中以public的形式导入hobby.proto
,basic_data.proto
位于protocol/basic_data下,内容入下:
syntax = "proto3";
// 把包名去掉等于本proto内为全局命名空间 把包名加上则为basic_data命名空间
package basic_data;
import public "hobby/hobby.proto";
// import "google/protobuf/any.proto";
message student
{
message individual_info
{
string address = 1;
string birthday = 2;
bool is_male = 3;
}
int32 index = 1;
individual_info info = 2;
string name = 3;
}
message student_list
{
repeated student students = 1;
}
在shell脚本中进行代码生成,脚本如下:
#!/bin/bash
PROTOCOL_PATH=./protocol
declare -a PROTOCOL_ARRAY=(hobby basic_data)
for i in ${PROTOCOL_ARRAY[@]}
do
:
# --cpp_out基于PROTOCOL_PATH,再相对于--proto_path下的文件目录创建产物的路径
# 如: 产物hobby.pb.*的路径为: ./protocol + booby/ ===> ./protocol/booby
protoc --cpp_out=${PROTOCOL_PATH} ${i}/${i}.proto --proto_path=${PROTOCOL_PATH}
done
执行后,生成的.h 和 .cc出现在下图所示位子:
然后我的测试代码如下:
#include <fcntl.h>
#include <gtest/gtest.h>
#include <unistd.h>
#include <algorithm>
#include <iostream>
#include <string>
#include "protocol/basic_data/basic_data.pb.h"
TEST(serialize_and_parse_unittest, TEST1) {
using namespace basic_data;
student liming{};
liming.set_name("liming");
liming.set_index(1);
if (auto liming_individual_info = liming.mutable_info();
liming_individual_info) {
liming_individual_info->set_address("china");
liming_individual_info->set_birthday("29/2/1996");
liming_individual_info->set_is_male(true);
}
student xiaohong{};
xiaohong.set_name("xiaohong");
xiaohong.set_index(2);
if (auto xiaohong_individual_info = xiaohong.mutable_info();
xiaohong_individual_info) {
xiaohong_individual_info->set_address("china");
xiaohong_individual_info->set_birthday("28/2/1996");
xiaohong_individual_info->set_is_male(false);
}
// student_list
student_list class_members{};
class_members.add_students()->CopyFrom(liming);
class_members.add_students()->CopyFrom(xiaohong);
// serialize
if (int fd = open("mark.txt", O_WRONLY | O_CREAT, 0755); fd > 0) {
class_members.SerializePartialToFileDescriptor(fd);
close(fd);
}
// parse
if (int fd = open("mark.txt", O_RDONLY, 0755); fd > 0) {
class_members.Clear();
class_members.ParseFromFileDescriptor(fd);
close(fd);
for (auto &&member : class_members.students()) {
if (member.has_info()) {
std::cout << "name:" << member.name() << "- :" << member.index()
<< "\n";
auto &&info = member.info();
std::cout << "address:" << info.address() << "\n";
std::cout << "birthday:" << info.birthday() << "\n";
std::cout << "is_male:" << info.is_male() << "\n";
}
}
}
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.6)
set(CMAKE_BUILD_TYPE "Debug")
project(protobuf_test
LANGUAGES C CXX
)
set(PREFIX_THIS_PROJECT ..)
set(PROTOCOL_PATH ${PREFIX_THIS_PROJECT}/protocol)
file(GLOB_RECURSE PROTOCOL_CC ${PROTOCOL_PATH}/*.cc)
find_package(GTest REQUIRED)
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${PREFIX_THIS_PROJECT})
include_directories(${PROTOCOL_PATH})
enable_testing()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -pipe -std=c++17 -fno-exceptions")
set(TEST_LIST
serialize_and_parse_unittest
)
foreach(src ${TEST_LIST})
add_executable(${src} ${src}.cc ${PROTOCOL_CC})
target_link_libraries(${src} ${Protobuf_LIBRARIES} GTest::GTest GTest::Main)
add_test(${src} ${src})
endforeach()