Protobuf反射功能

#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/

https://blog.csdn.net/solstice/article/details/6300108

猜你喜欢

转载自www.cnblogs.com/oyld/p/12389828.html
今日推荐