第一个 Protocol Buffers 小程序

来源:互联网 发布:淘宝如何买烟 编辑:程序博客网 时间:2024/06/06 11:49

首先从 Protocol Buffers 的主页上把源码下回来,注意是源码,那个 Win32 包不必下,它里面只有一个编译好的 protoc.exe,没有开发所必须的库,光有那个 Protocol Buffers 编译器是没用。

将源码解压出来以后,直接到 vsprojects 目录下用 Visual Studio 2005(其它版本我没有试)打开解决方案文件 protobuf.sln 开始编译。编译成功结束后会在解决方案目录下生成一个 google 目录,里面是单元测试的程序;另外就是 Debug 目录和 Release 目录了,生成的对应版本的 .lib 和 .dll 还有 protoc.exe 编译器全在里面。

那么,头文件呢?在解决方案目录下有一个 extract_includes.bat 文件看到了吗,执行后会生成一个 include 目录,里面就是使用 Protocol Buffers 开发必须的所有头文件了。

HiaHia~ 有了这几样东西,Protocol Buffers 这个强大武器才算是真正到手了。在动手写我们自己的程序之前,为了方便,你也可以把库文件和头文件单独存放在别处,然后在 VC 里设置 VC++ 目录就行了,还有别忘了把 .dll 所在的目录加到系统的 Path 环境变量中。好了,现在我们可以开始动手写自己的程序啦!其实这个程序就是 Protocol Buffers 文档中的电话本例子,只不过我自己试了一遍而已。

第一步,写一个 .proto 文件描述数据结构:

// addressbook.proto
//

 

package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;        // Unique ID number for this person.
  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;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person person = 1;
}

 

第二步,使用命令 protoc.exe -I=. --cpp_out=. addressbook.proto 编译 addressbook.proto,或者方便起见,在 VC 里给 addressbook.proto 设置自定义生成步骤,命令还是这一行,输出文件设置为 addressbook.pb.h;addressbook.pb.cc。

第三步,新建 testProtocolBuffers.cpp,写入下面的代码:

// testProtocolBuffers.cpp : Defines the entry point for the console application.
//

 

#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
#pragma comment(lib, "libprotobuf.lib")

void PromptForAddress(tutorial::Person* person);
void ListPeople(const tutorial::AddressBook& addressbook);

int AddPerson();
int ViewPerson();

int _tmain(int argc, _TCHAR* argv[])
{
    AddPerson();
    ViewPerson();
    return 0;
}

void PromptForAddress(tutorial::Person* person)
{
    std::cout <<"Enter person ID number: ";
    int id;
    std::cin>> id;
    person->set_id(id);
    std::cin.ignore(256, '/n');

    std::cout <<"Enter name: ";
    std::getline(std::cin, *person->mutable_name());

    std::cout <<"Enter email address (blank for none): ";
    std::string email;
    std::getline(std::cin, email);
    if (!email.empty())
        person->set_email(email);

    while (true)
    {
        std::cout <<"Enter a phone number (or leave blank to finish): ";
        std::string number;
        std::getline(std::cin, number);
        if (number.empty())
            break;

        tutorial::Person::PhoneNumber* phonenum = person->add_phone();
        phonenum->set_number(number);

        std::cout <<"Is it a mobile, home or work phone? ";
        std::string type;
        std::getline(std::cin, type);
        if ("mobile" == type)
            phonenum->set_type(tutorial::Person::MOBILE);
        else if ("home" == type)
            phonenum->set_type(tutorial::Person::HOME);
        else if ("work" == type)
            phonenum->set_type(tutorial::Person::WORK);
        else
            std::cout <<"Unknown phone type. Using default." <<std::endl;
    }
}

void ListPeople(const tutorial::AddressBook& addressbook)
{
    for (int i = 0; i <addressbook.person_size(); i++)
    {
        const tutorial::Person& person = addressbook.person(i);
        std::cout <<"Person ID: " <<person.id() <<std::endl;
        std::cout <<"Name: " <<person.name() <<std::endl;
        if (person.has_email())
            std::cout <<"Email: " <<person.email() <<std::endl;

        for (int j = 0; j <person.phone_size(); j++)
        {
            const tutorial::Person::PhoneNumber& phonenum = person.phone(j);
            switch (phonenum.type())
            {
            case tutorial::Person::MOBILE:
                std::cout <<"Mobile phone #: ";
                break;
            case tutorial::Person::HOME:
                std::cout <<"Home phone #: ";
                break;
            case tutorial::Person::WORK:
                std::cout <<"Work phone #: ";
                break;
            }
            std::cout <<phonenum.number() <<std::endl;
        }
    }
}

int AddPerson()
{
    tutorial::AddressBook addressbook;
    const std::string& filename = "addressbook";
    std::fstream input(filename.c_str(), ios::in | ios::binary);
    if (!input)
        std::cout <<filename <<": File not found. Creating a new file." <<std::endl;
    else if (!addressbook.ParseFromIstream(&input))
    {
        std::cerr <<"Failed to parse address book." <<std::endl;
        return -1;
    }
    PromptForAddress(addressbook.add_person());
    std::fstream output(filename.c_str(), ios::out | ios::trunc | ios::binary);
    if (!addressbook.SerializeToOstream(&output))
    {
        std::cerr <<"Failed to write address book." <<std::endl;
        return -1;
    }
    return 0;
}

int ViewPerson()
{
    tutorial::AddressBook addressbook;
    const std::string& filename = "addressbook";
    std::fstream input(filename.c_str(), ios::in | ios::binary);
    if (!addressbook.ParseFromIstream(&input))
    {
        std::cerr <<"Failed to parse address book." <<std::endl;
        return -1;
    }
    ListPeople(addressbook);
    return 0;
}

 

编译——链接,这样我们的第一个程序,基于 Protocol Buffers 的电话本就写好了。时间关系,这篇日志写得很匆忙。程序在 VC2005 下测试通过,但这只是一个小例子,至于 Protocol Buffers 的性能和效率还没有来得及进一步测试。^_^