欢迎访问我的博客首页。
Protobuf 是 gRPC 的依赖之一,可以直接安装 gRPC。
1. 生成源文件
使用 CMake 编译工具,根据 xxx.proto 生成 xxx.pb.h 和 xxx.pb.cc。整个工程有三个文件,第一个文件是 AddressBook.proto,内容如下。
package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
第二个文件是代码文件 main.cpp,内容如下。
#include "AddressBook.pb.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
// 根据用户输入,向地址簿添加一个人的信息。
void PromptForAddress(tutorial::Person *person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, '\n');
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber *phone_number = person->add_phone();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << "Unknown phone type. Using default." << endl;
}
}
}
// Main function: Reads the entire address book from a file,
// adds one person based on user input, then writes it back out to the same
// file.
int main(int argc, char *argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << ": File not found. Creating a new file." << endl;
} else if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
// Add an address.
PromptForAddress(address_book.add_person());
{
// Write the new address book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
第三个文件是 CMake 配置文件 CMakeLists.txt,用于根据 xxx.proto 生成 xxx.pb.h 和 xxx.pb.cc,且把代码文件编译成可执行文件。内容如下。
cmake_minimum_required(VERSION 3.2)
project(Protobuf_example)
set(absl_DIR D:/MinGW/libraries/abseil/lib/cmake/absl)
find_package(absl REQUIRED)
set(absl_LIBRARIES
absl::algorithm
absl::base
absl::debugging
absl::flat_hash_map
absl::memory
absl::meta
absl::numeric
absl::str_format
absl::strings
absl::synchronization
absl::time
absl::utility
)
find_package(Protobuf 3.0.0 REQUIRED)
PROTOBUF_GENERATE_CPP(PROTO_HDRS PROTO_SRCS AddressBook.proto)
#message(Protobuf_INCLUDE_DIRS = ${Protobuf_INCLUDE_DIRS})
#message(Protobuf_LIBRARIES = ${Protobuf_LIBRARIES})
#message(PROTO_SRCS = ${PROTO_SRCS})
#message(PROTO_HDRS = ${PROTO_HDRS})
add_executable(${PROJECT_NAME}
main.cpp
${PROTO_SRCS}
${PROTO_HDRS}
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
${PROTOBUF_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
${PROTOBUF_LIBRARIES}
${absl_LIBRARIES}
)
CMake 使用命令 PROTOBUF_GENERATE_CPP 根据 xxx.proto 生成 xxx.pb.h 和 xxx.pb.cc。这个命令来自位于 Protobuf 安装位置 bin 文件夹中的 protoc.exe,因此要确保该路径在环境变量中。