简要介绍和总结protobuf的一些关键点,从我以前作的ppt里摘录而成,但愿能节省protobuf初学者的入门时间。这是一个简单的Demo。html
Protobuf全称Google Protocol Buffersjava
消息定义文件user_def.protopython
package user; message UserInfo { required int64 id = 1; optional string name = 2; repeated bytes nick_name = 3; }
编译.proto,生成解析器代码linux
protoc --cpp_out . user.proto // user_def.pb.h user_def.pb.cc protoc --java_out . user.proto // user/UserInfo.java
optional string name = 2
;c++
https://developers.google.com/protocol-buffers/docs/proto#scalargit
string vs. bytesgithub
.proto类型 | c++类型 | java类型 | 说明 |
---|---|---|---|
string | std::string | String | 必须是UTF-8或ASCII文本 |
bytes | std::string | ByteString | 任意的字节序列 |
反射是protobuf的一个重要特性,涉及到的类主要有:json
如下是一个根据消息名(包含package name)建立protobuf消息的C++函数,须要注意的是返回的消息必须在用完后delete掉。函数
Message* createMessage(const string &typeName) { Message *message = NULL; // 查找message的descriptor const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); if (descriptor) { // 建立default message(prototype) const Message *prototype = MessageFactory::generated_factory()->GetPrototype(descriptor); if (NULL != prototype) { // 建立一个可修改的message message = prototype->New(); } } return message; }
根据消息的字段名称修改其值。以上面的user.UserInfo为例,下面将一个新的UserInfo消息的其id字段设为100。post
int main() { // 使用上面的函数建立一个新的UserInfo message Message *msg = createMessage("user.UserInfo"); if (NULL == msg) { // 建立失败,多是消息名错误,也多是编译后message解析器 // 没有连接到主程序中。 return -1; } // 获取message的descriptor const Descriptor* descriptor = msg->GetDescriptor(); // 获取message的反射接口,可用于获取和修改字段的值 const Reflection* reflection = msg->GetReflection(); // 根据字段名查找message的字段descriptor const FieldDescriptor* idField = descriptor->FindFieldByName("id"); // 将id设置为100 if (NULL != idField) { reflection->SetInt64(msg, idField, 100); } // ... 其余操做 // 最后删除message delete msg; return 0; }
用createMessage建立一个空的消息后,最多见的使用场景是使用Message的ParseFromString或ParseFromIstream方法从字符串或流中读取一个序列化后的message。
Message *msg = createMessage("user.UserInfo"); if (NULL != msg) { if (!msg->ParseFromString("... serialized message string ... ")) { // 解析失败 ... } }