protobuf支持vs2019_C++使用ProtoBuff(VS2017 + ProtoBuff3.13 + X64)

下载ProtoBuff

从github下载:

说明:

直接clone下来的代码,没有子模块(引用的其他第三方模块的代码),比如third_party/googletest;

编译ProtoBuff

解压protobuf-3.13.0后,命令行进入protobuf-3.13.0目录

cd D:\work\program\open_source\protobuf-all-3.13.0\protobuf-3.13.0

新建一个编译输出路径

mkdir build_1 && cd build_1

执行cmake, 生成VS2017工程文件;

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" ../cmake -G "Visual Studio 15 2017 Win64"

说明:

-G "Visual Studio 15 2017 Win64" 表示生成VS2017 X64工程;

../cmake 表示CMakeLists.txt文件的路径

生成include文件

extract_includes.bat

打开build_1/protobuf.sln,进行编译

这样,就得到了我们需要的头文件、protoc.exe、libprotobufd.lib(PS:libprotobuf只提供了静态库),在如下两个目录:

protobuf-3.13.0/build_1/Debug

protobuf-3.13.0/build_1/include

注意:

Protobuf的所有工程默认运行库是MT/MTd,建议都改成MD/MDd;

如果不修改,那么你的工程也必须设置成MT/MTd才能编译通过,这样如果在使用其他动态库时,很容易导致一些堆错误,因为动态库相对应用有独立heap;

101fbc1a4828

image.png

使用ProtoBuff

先把生成的Debug和include拷贝到工程目录

101fbc1a4828

image.png

PS:D:\work\program\Serialization\Serialization是我的测试工程目录*

添加一个测试proto文件

Serialization\protobuff_files\AddressBook.proto

syntax = "proto3";

package tutorial;

message Person {

string name = 1;

int32 id = 2;

string email = 3;

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

string number = 1;

PhoneType type = 2;

}

repeated PhoneNumber phones = 4;

}

message AddressBook {

repeated Person people = 1;

}

编译proto文件

进入测试工程目录

cd D:\work\program\Serialization\Serialization

使用编译生成的protoc.exe编译proto文件

protobuf-3.13.0\x64\Debug\protoc.exe -I=Serialization\protobuff_files --cpp_out=Serialization\protobuff_files AddressBook.proto

说明:

protoc编译.proto文件命令格式:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR xxx1.proto xxx2.proto

$SRC_DIR:包含相关的所有.proto文件,一般为工程目录;

$DST_DIR:生成的源文件的目录,可以与$SRC_DIR相同;

xxx1.proto:proto文件在$SRC_DIR中的相对路径,也可以是绝对路径;

编译proto文件后,会生成对应的.pb.cc和.pb.h文件:

101fbc1a4828

image.png

应用工程设置

PS:老手请跳过此步;

包含include目录:$(ProjectDir)..\protobuf-3.13.0\x64\include;

101fbc1a4828

image.png

添加库目录:$(ProjectDir)..\protobuf-3.13.0\x64\Debug;

101fbc1a4828

image.png

添加附加依赖项:libprotobufd.lib;

101fbc1a4828

image.png

添加编译proto生成的AddressBook.pb.cc和AddressBook.pb.h到工程:

101fbc1a4828

image.png

使用ProtoBuff示例

代码可以直接拷贝运行

/************************************************************************

* 测试ProtoBuff

*

*

* 从didi_AddressBook.txt中读取通讯录,然后添加一条记录,最后再写入文件;

* 如果didi_AddressBook.txt不存在,第一次添加记录后,会创建文件didi_AddressBook.txt

*

************************************************************************/

#include

#include

#include

#include "protobuff_files/AddressBook.pb.h"

using namespace std;

// 打印AddressBook

void ListPeople(const tutorial::AddressBook& address_book) {

for (int i = 0; i < address_book.people_size(); i++) {

const tutorial::Person& person = address_book.people(i);

cout << "Person ID: " << person.id() << endl;

cout << " Name: " << person.name() << endl;

cout << " E-mail address: " << person.email() << endl;

for (int j = 0; j < person.phones_size(); j++) {

const tutorial::Person::PhoneNumber& phone_number = person.phones(j);

switch (phone_number.type()) {

case tutorial::Person::MOBILE:

cout << " Mobile phone #: ";

break;

case tutorial::Person::HOME:

cout << " Home phone #: ";

break;

case tutorial::Person::WORK:

cout << " Work phone #: ";

break;

}

cout << phone_number.number() << endl;

}

}

}

// 通讯录增加一个人

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_phones();

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;

}

}

}

// 从didi_AddressBook.txt中读取通讯录,然后添加一条记录,最后再写入文件;

// 如果didi_AddressBook.txt不存在,第一次添加记录后,会创建文件didi_AddressBook.txt

int main(int argc1, char* argv1[]) {

// 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;

char file_name[] = "didi_AddressBook.txt";

tutorial::AddressBook address_book;

{

// Read the existing address book.

fstream input(file_name, ios::in | ios::binary);

if (!input) {

cout << file_name << ": File not found. Creating a new file." << endl;

}

else if (!address_book.ParseFromIstream(&input)) {

cerr << "Failed to parse address book." << endl;

return -1;

}

}

//打印address_book

{

int people_size = address_book.people_size();

cout << "print address_book by ListPeople(): " << people_size << endl;

ListPeople(address_book);

//也可以使用基类Message中提供的方法:

string debug_string = address_book.DebugString();

cout << "print address_book by PrintDebugString(): " << endl;

address_book.PrintDebugString();

address_book.Clear();

cout << "after Clear, print address_book by PrintDebugString(): " << endl;

address_book.PrintDebugString();

cout << endl;

}

// Add an address.

cout << "begin add a address:" << endl;

PromptForAddress(address_book.add_people());

{

// Write the new address book back to disk.

fstream output(file_name, 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;

}

可以看到ProtoBuff序列化后的内容如下:

101fbc1a4828

image.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值