00. 目录
文章目录
-
- 01. 枚举消息格式
- 02. 枚举测试代码
- 03. 编译和测试
- 04. 包的消息格式
- 05. 包的测试程序
- 06. 编译和测试
- 07. 附录
当需要定义一个消息类型的时候,可能想为一个字段指定某“预定义值序列”中的一个值,这时候可以通过枚举实现。
syntax = "proto3";//指定版本信息,不指定会报错 message Person //message为关键字,作用为定义一种消息类型 { string name = 1; //姓名 int32 id = 2; //id string email = 3; //邮件 enum PhoneType //枚举消息类型 { MOBILE = 0; //proto3版本中,首成员必须为0,成员不应有相同的值 HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; //phones为数组 } message AddressBook { repeated Person people = 1; }
生成对应文件
deng@itcast:/mnt/hgfs/LinuxHome/day03$ protoc addressbook.proto --cpp_out=./ deng@itcast:/mnt/hgfs/LinuxHome/day03$
#include "addressbook.pb.h" #include <iostream> #include <fstream> using namespace std; void set_addressbook() { AddressBook obj; Person *p1 = obj.add_people(); //新增加一个Person p1->set_name("tom"); p1->set_id(1); p1->set_email("[email protected]"); Person::PhoneNumber *phone1 = p1->add_phones(); //增加一个phone phone1->set_number("110"); phone1->set_type(Person::MOBILE); Person::PhoneNumber *phone2 = p1->add_phones(); //增加一个phone phone2->set_number("120"); phone2->set_type(Person::HOME); fstream output("pb.itcast", ios::out | ios::trunc | ios::binary); bool flag = obj.SerializeToOstream(&output);//序列化 if (!flag) { cerr << "Failed to write file." << endl; return; } output.close();//关闭文件 } void get_addressbook() { AddressBook obj; fstream input("./pb.itcast", ios::in | ios::binary); obj.ParseFromIstream(&input); //反序列化 input.close(); //关闭文件 for (int i = 0; i < obj.people_size(); i++) { const Person& person = obj.people(i);//取第i个people cout << "第" << i + 1 << "个信息\n"; cout << "name = " << person.name() << endl; cout << "id = " << person.id() << endl; cout << "email = " << person.email() << endl; for (int j = 0; j < person.phones_size(); j++) { const Person::PhoneNumber& phone_number = person.phones(j); switch (phone_number.type()) { case Person::MOBILE: cout << " Mobile phone #: "; break; case Person::HOME: cout << " Home phone #: "; break; case Person::WORK: cout << " Work phone #: "; break; } cout << phone_number.number() << endl; } cout << endl; } } int main() { // 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; set_addressbook(); //序列化 get_addressbook(); //反序列化 // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; }
编译和测试结果
deng@itcast:/mnt/hgfs/LinuxHome/day03$ g++ test.cpp addressbook.pb.cc `pkg-config --libs --cflags protobuf` deng@itcast:/mnt/hgfs/LinuxHome/day03$ ./a.out 第1个信息 name = tom id = 1 email = [email protected] Mobile phone #: 110 Home phone #: 120 deng@itcast:/mnt/hgfs/LinuxHome/day03$
.proto文件新增一个可选的package声明符,用来防止不同的消息类型有命名冲突。包的声明符会根据使用语言的不同影响生成的代码。对于C++,产生的类会被包装在C++的命名空间中。
syntax = "proto3";//指定版本信息,不指定会报错 package tutorial; //package声明符 message Person //message为关键字,作用为定义一种消息类型 { string name = 1; //姓名 int32 id = 2; //id string email = 3; //邮件 enum PhoneType //枚举消息类型 { MOBILE = 0; //proto3版本中,首成员必须为0,成员不应有相同的值 HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; //phones为数组 } message AddressBook { repeated Person people = 1; }
#include "addressbook.pb.h" #include <iostream> #include <fstream> using namespace std; void set_addressbook() { tutorial::AddressBook obj; tutorial::Person *p1 = obj.add_people(); //新增加一个Person p1->set_name("tom"); p1->set_id(1); p1->set_email("[email protected]"); tutorial::Person::PhoneNumber *phone1 = p1->add_phones(); //增加一个phone phone1->set_number("110"); phone1->set_type(tutorial::Person::MOBILE); tutorial::Person::PhoneNumber *phone2 = p1->add_phones(); //增加一个phone phone2->set_number("120"); phone2->set_type(tutorial::Person::HOME); fstream output("pb.itcast", ios::out | ios::trunc | ios::binary); bool flag = obj.SerializeToOstream(&output);//序列化 if (!flag) { cerr << "Failed to write file." << endl; return; } output.close();//关闭文件 } void get_addressbook() { tutorial::AddressBook obj; fstream input("./pb.itcast", ios::in | ios::binary); obj.ParseFromIstream(&input); //反序列化 input.close(); //关闭文件 for (int i = 0; i < obj.people_size(); i++) { const tutorial::Person& person = obj.people(i);//取第i个people cout << "第" << i + 1 << "个信息\n"; cout << "name = " << person.name() << endl; cout << "id = " << person.id() << endl; cout << "email = " << 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; } cout << endl; } } int main() { // 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; set_addressbook(); //序列化 get_addressbook(); //反序列化 // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; }
编译和测试
deng@itcast:/mnt/hgfs/LinuxHome/day03$ g++ test.cpp addressbook.pb.cc `pkg-config --libs --cflags protobuf` deng@itcast:/mnt/hgfs/LinuxHome/day03$ ./a.out 第1个信息 name = tom id = 1 email = [email protected] Mobile phone #: 110 Home phone #: 120 deng@itcast:/mnt/hgfs/LinuxHome/day03$