内容纲要

[code]
git clone –depth=1 https://github.com/google/protobuf.git
git submodule update –init –recursive
[/code]

设置 cmake 路径,生成工程

[code]
@set path=D:\rover2\nginxstack\cmake\bin;%PATH%
echo Building C++
mkdir build_msvc
cd build_msvc
cmake -G "Visual Studio 15 2017" -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_UNICODE=ON ../cmake
msbuild protobuf.sln /p:Platform=Win32 || goto error
cd Debug
tests.exe || goto error

pause
[/code]

编译后生成了

[code]
protoc.exe
libprotocd.dll
libprotocd.lib
libprotobufd.dll
libprotobufd.lib
[/code]

我们首先定义一个addressbook.proto, 通过message来定义需要序列化的数据结构, message 内包含许多 key-value 对

[cpp]
// See README.txt for information and build instructions.
//
// Note: START and END tags are used in comments to define sections used in
// tutorials. They are not part of the syntax for Protocol Buffers.
//
// To get an in-depth walkthrough of this file and the related examples, see:
// https://developers.google.com/protocol-buffers/docs/tutorials

// [START declaration]
syntax = "proto3";
package tutorial;

import "google/protobuf/timestamp.proto";
// [END declaration]

// [START java_declaration]
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
// [END java_declaration]

// [START csharp_declaration]
option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
// [END csharp_declaration]

// [START messages]
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;

enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}

message PhoneNumber {
string number = 1;
PhoneType type = 2;
}

repeated PhoneNumber phones = 4;

google.protobuf.Timestamp last_updated = 5;
}

// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
// [END messages]
[/cpp]

  1. message中有多种类型, bool, int32, float, double, ,string and enum以及内嵌的message
  2. message内可以定义 optional、required、repeated 字段

定义好 *.proto 文件后, 我们通过 protobuf 提供的 protoc 命令行工具来自动生成相关数据结构源码

protoc_build.bat

[code]
@set PATH=D:\protobuf\build_msvc\Release;%PATH%
protoc -I=./ -I=D:/protobuf/src –cpp_out=./ ./addressbook.proto
[/code]

  • -I 指明源文件所在目录
  • --cpp_out 指向想要输出的文件路径
  • 最后一个参数为 .proto 所在的路径

add_person.cpp

[cpp]
// See README.txt for information and build instructions.

#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;

// This function fills in a Person message based on user input.
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; } } *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
}

// 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_people());
{
// 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;
}
[/cpp]

list_person.cpp

[cpp]
// See README.txt for information and build instructions.

#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;

// Iterates though all people in the AddressBook and prints info about them.
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;

if (person.email() != "") {
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;

default:
cout << " Unknown phone #: ";
break;
}

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

if (person.has_last_updated()) {
cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << endl;
}
}
}

// Main function: Reads the entire address book from a file and prints all
// the information inside.
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 (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
ListPeople(address_book);
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
[/cpp]

premake5.lua

[cpp]
project "protobuf-example-add-person"
kind "ConsoleApp"
flags { "NoManifest", "WinMain" }
defines { "PROTOBUF_USE_DLLS" }
files
{
"protobuf-example/*.h",
"protobuf-example/*.cpp",
"protobuf-example/*.cc",
}
removefiles
{
"protobuf-example/list_person.cpp",
}
includedirs
{
"D:/protobuf/src"
}
libdirs
{
"D:/protobuf/build_msvc/Release"
}
links
{
"libprotobuf.lib"
}

project "protobuf-example-list-person"
kind "ConsoleApp"
flags { "NoManifest", "WinMain" }
defines { "PROTOBUF_USE_DLLS" }
files
{
"protobuf-example/*.h",
"protobuf-example/*.cpp",
"protobuf-example/*.cc",
}
removefiles
{
"protobuf-example/add_person.cpp",
}
includedirs
{
"D:/protobuf/src"
}
libdirs
{
"D:/protobuf/build_msvc/Release"
}
links
{
"libprotobuf.lib"
}
[/cpp]

编译后运行示例

[code]
protobuf-example-add-person.exe test.dat
protobuf-example-list-person.exe test.dat
[/code]

其他

发表评论

电子邮件地址不会被公开。 必填项已用*标注