#include <string> #include <map> #include <google/protobuf/message.h> #include <google/protobuf/descriptor.h> #include "person.pb.h" using namespace std; string package; typedef void (*CallbackFunc)(const string &type_name, google::protobuf::Message *message); // descriptor -> callback map<const google::protobuf::Descriptor *, CallbackFunc> write_callbacks; map<const google::protobuf::Descriptor *, CallbackFunc> read_callbacks; google::protobuf::Message *CreateMessage(const std::string &type_name) { google::protobuf::Message *message = NULL; const google::protobuf::Descriptor *descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name); if (descriptor) { const google::protobuf::Message *prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor); if (prototype) { message = prototype->New(); } } return message; } void WriteHead(const string &type_name) { package.append(to_string(type_name.length()).c_str(), 2); package.append(type_name.c_str(), type_name.length()); } void WritePayload(const string &data) { package.append(to_string(data.length()).c_str(), 2); package.append(data.c_str(), data.length()); } // 业务逻辑,负责构造pb并序列化 void OnStudentWrite(const string &type_name, google::protobuf::Message *arg) { WriteHead(type_name); person::Student *student = (person::Student *) arg; student->set_name("xiaoming"); student->set_age(10); string data = student->SerializeAsString(); WritePayload(data); } // 业务逻辑,负责构造pb并序列化 void OnTeacherWrite(const string &type_name, google::protobuf::Message *arg) { WriteHead(type_name); person::Teacher *teacher = (person::Teacher *) arg; teacher->set_name("shelly"); teacher->set_email("[email protected]"); string data = teacher->SerializeAsString(); WritePayload(data); } // 业务逻辑,负责反序列化解出pb void OnStudentRead(const string &data, google::protobuf::Message *arg) { person::Student *student = (person::Student *) arg; student->ParseFromString(data); printf("name:%s age:%d\n", student->name().c_str(), student->age()); } // 业务逻辑,负责反序列化解出pb void OnTeacherRead(const string &data, google::protobuf::Message *arg) { person::Teacher *teacher = (person::Teacher *) arg; teacher->ParseFromString(data); printf("name:%s email:%s\n", teacher->name().c_str(), teacher->email().c_str()); } void WriteDispatcher(const string &type_name) { const google::protobuf::Descriptor *descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name); auto find = write_callbacks.find(descriptor); if (find != write_callbacks.end()) { google::protobuf::Message *message = CreateMessage(type_name); find->second(type_name, message); // down casting delete message; } } // 解包,根据pb类型调用对应的业务处理函数 void ReadDispatcher() { size_t pos = 0; while (pos < package.length()) { uint16_t type_len = atoi(package.substr(pos, 2).c_str()); pos += 2; string type_name = package.substr(pos, type_len); pos += type_len; const google::protobuf::Descriptor *descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name); if (read_callbacks.count(descriptor) == 0) { continue; // 找不到type name对应的callback } uint16_t data_len = atoi(package.substr(pos, 2).c_str()); pos += 2; string data = package.substr(pos, data_len); google::protobuf::Message *message = CreateMessage(type_name); pos += data_len; read_callbacks[descriptor](data, message); // down casting delete message; } } void RegisteCallback() { write_callbacks.insert(make_pair(person::Student::descriptor(), OnStudentWrite)); write_callbacks.insert(make_pair(person::Teacher::descriptor(), OnTeacherWrite)); read_callbacks.insert(make_pair(person::Student::descriptor(), OnStudentRead)); read_callbacks.insert(make_pair(person::Teacher::descriptor(), OnTeacherRead)); } int main() { RegisteCallback(); WriteDispatcher("person.Student"); WriteDispatcher("person.Teacher"); ReadDispatcher(); return 0; }
参考
http://senlinzhan.github.io/2016/11/12/protobuf%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8F%8D%E5%B0%84/