protobuf C++

protobuf C++

学习Caffe 无可避免的要学习和了解一下protobuf.
Caffe使用的是proto2版本。因此,我们下面下载proto2.

Caffe中使用的是(caffe.pb.h文件中)可以看到:

#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3001000

即caffe.hp.h和caffe.hp.cc是使用protoc-3.1.0编译生成的。

:这里总是给人误解,proto2的版本(proto2和proto3语法发生了某些变化),给出的protoc编译器却是protoc-3.1.0以3开头的。

protobuf 官方文档:

https://developers.google.com/protocol-buffers/docs/cpptutorial

  1. Define message formats in a .proto file.
  2. Use the protocol buffer compiler.
  3. Use the C++ protocol buffer API to write and read messages.

就像官网说的那样,仅需三个步骤就搞定:

  1. 定义一个.proto文件
  2. 使用protoc.exe编译.proto文件,生成.h和.cpp文件
  3. 使用C++protoAPI读写信息。

protobuf编译工具下载和安装:

旧版本下载地址:

http://repo1.maven.org/maven2/com/google/protobuf/protoc/

因为我们的Caffe代码包含了所需要的proto头文件和库文件,因此我们直接下载的可执行文件:

protoc-3.1.0-windows-x86_64.exe

使用下面的命令参数:

protoc-3.1.0-windows-x86_64.exe -I="E:/" --cpp_out="E:/" "E:/addressbook.proto" 

格式为:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

然后在文E盘下就生成两个文件:addressbook.pb.cc 和 addressbook.pb.h

:生成的两个文件依赖proto头文件和库文件,请确保自己电脑上面含有。

写消息:write_message.cpp


#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<string>
#include"addressbook.pb.h"
using namespace std;

//this funtion fill 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:";
    //使用指针的形式,设置成员的值,->优先级高于*,mutable_name返回string类型的指针,通过*进行解引用操作。
    getline(cin, *person->mutable_name());
    cout << "Enter email address (blank for none):";
    string email;
    getline(cin, email);
    if (!email.empty())
    {
        //使用set函数设置成员的值
        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;
        }
        //message中嵌套类型的使用:首先获取地址,然而对嵌套中的成员进行值的读写
        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")
        {
            //message中枚举类型的使用
            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函数,从文件中读取完整的address book
用输入的方式来增加一个person,然后将其入同样的文件中。
*/
int main(int argc, char* argv[])
{
    //检查连接的库的版本和编译的头文件的版本是否兼容
    //GOOGLE_PROTOBUF_VERIFY_VERSION;
    if (argc != 2)
    {
        cerr << "usage: " << argv[0] << "ADDRESS_BOOK_FILE" << endl;
        return -1;
    }
    tutorial::AddressBook address_book;
    {
        //读取现有的 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;
        }

    }
    //增加一个address
    PromptForAddress(address_book.add_person());
    {
        //将新的address 写回到disk
        //ios::trunc写入前先将内容全部清空
        fstream output(argv[1], ios::out | ios::trunc | ios::binary);
        if (!address_book.SerializeToOstream(&output))
        {
            cerr << "Failed to write address book. " << endl;
            return -1;
        }
    }
    //可选的:删除libprotobuf分配的所有全局对象
    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}

读消息: read_message.cpp

#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<string>
#include"addressbook.pb.h"

using namespace std;

//迭代的访问addressbook中的所有人,并且打印输出他们的信息
void ListPeople(const tutorial::AddressBook& address_book)
{
    for (int i = 0; i < address_book.person_size(); i++)
    {
        const tutorial::Person &person = address_book.person(i);
        cout << "Person ID: " << person.id() << endl;
        cout << "Name: " << person.name() << endl;
        if (person.has_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;
            }
            cout << phone_number.number() << endl;
        }
    }

}

//main 函数:从file 中读取完整的adress,并且打印出内部的所有信息
int main(int argc, char * argv[])
{
    //验证连接库的版本和编译的头文件的版本是否一致
    GOOGLE_PROTOBUF_VERIFY_VERSION;
    if (argc != 2)
    {
        cerr << "usage: " << argv[0] << " address_book_file" << endl;
        return -1;
    }
    tutorial::AddressBook address_book;
    {
        //读取现有的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);
    //可选的:删除libprotobuf分配的所有全局对象
    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}

caffe 中的protobuff

在caffe中,利用goolge的文本类型的类进行解析.prototxt文件,形如下:

tutorial::AddressBook address_book;
const char * filename = "addressbook.prototxt";
int fd = _open(filename, O_RDONLY);
FileInputStream * input = new FileInputStream(fd);
bool success = google::protobuf::TextFormat::Parse(input, &address_book);

解析后的内容全部存储在address_book对象中。

其中AddressBook就是上面通过编译器生成的类。

addressbook.prototxt文件的内容如下

person
{
 name : "zhangsan"
 id: 2011010227
}
person
{
 name: "lisi"
 id: 2011010339
 phones
 {
   number :"13026150789"
   type: WORK
 }
}

测试的主函数定义如下

#include "stdafx.h"


#include<google/protobuf/io/zero_copy_stream_impl.h>
#include<google/protobuf/text_format.h>

#include"addressbook.pb.h"
#include<iostream>
#include<fstream>
using namespace std;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;


#include<fcntl.h>
#include<io.h> //for windows

int main(void)
{

    // protobuf 的使用
    tutorial::AddressBook address_book;
    const char * filename = "addressbook.prototxt";
    int fd = _open(filename, O_RDONLY);
    FileInputStream * input = new FileInputStream(fd);
    bool success = google::protobuf::TextFormat::Parse(input, &address_book);

    //输出

    for (int i = 0; i < address_book.person_size(); i++)
    {
        cout << "Name :" << address_book.person(i).name();
        cout << ", ID :" << address_book.person(i).id();

        for (int j = 0; j < address_book.person(i).phones_size(); j++)
        {
            cout << ", PhoneNumber:" << address_book.person(i).phones(j).number();
        }
        cout << endl;
    }
}

运行结果
这里写图片描述

参考文献:

1 http://www.cnblogs.com/lidabo/p/3911456.html [protobuf c++入门]
2.http://blog.csdn.net/majianfei1023/article/details/45112415 [google protobuf学习笔记二:使用和原理]
3.http://blog.csdn.net/eclipser1987/article/details/8525383 [google protocol buffer (C++,Java序列化使用实例)]
4.http://blog.csdn.net/hailong0715/article/details/52057873 ProtoBuf安装和使用简介

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值