Protobuf 動態加載 .pb 文件並操作 Message


之前寫了《Protobuf 動態加載 .proto 文件並操作 Message》。除了直接讀取 .proto 文件之外,還有一種類似的方法。先把 .proto 文件編譯成 .pb 文件,再讀取 .pb 文件。這種方法雖然比直接讀取 .proto 多了一步,但是在運行期加載更快。
仍然使用之前的的 .proto 文件作為示例。使用 protoc.proto 文件編譯為 .pb 文件。

./3rdparty/bin/protoc -I./proto -oaddressbook.pb --include_imports ./proto/addressbook.proto

注意,這里有兩個 .proto 文件,應該選擇沒有被依賴的 .proto 文件作為參數,並且添加 --include_imports 選項。這樣,所有 .proto 文件及其依賴的 .proto 文件都被編進同一個 .pb 文件。

#include <iostream>
#include <fstream>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/util/json_util.h>
#include <google/protobuf/descriptor.pb.h>

using namespace google::protobuf;

int main()
{
    std::ifstream pb_file("./addressbook.pb", std::ios::binary);
    if (!pb_file.is_open())
    {
        return -1;
    }

    FileDescriptorSet file_descriptor_set;
    if (!file_descriptor_set.ParseFromIstream(&pb_file)) {
        return -1;
    }

    DescriptorPool pool;
    for (int i = 0; i < file_descriptor_set.file_size(); ++i) {
        pool.BuildFile(file_descriptor_set.file(i));
    }

    const Descriptor* person_descriptor = pool.FindMessageTypeByName("tutorial.Person");
    
    DynamicMessageFactory message_factory;
    const Message* default_person = message_factory.GetPrototype(person_descriptor);
    Message* person = default_person->New();

    const Reflection* reflection = person->GetReflection();
    reflection->SetString(person, person_descriptor->FindFieldByName("name"), "abc");
    reflection->SetInt32(person, person_descriptor->FindFieldByName("id"), 123456);
    reflection->SetString(person, person_descriptor->FindFieldByName("email"), "abc@163.com");

    util::JsonPrintOptions json_options;
    json_options.add_whitespace = true;
    json_options.always_print_primitive_fields = true;
    json_options.preserve_proto_field_names = true;
    std::string output;
    util::MessageToJsonString(*person, &output, json_options);
    std::cout << "====== Person data ======" << std::endl;
    std::cout << output;

    delete person;
}

輸出

====== Person data ======
{
 "name": "abc",
 "id": 123456,
 "email": "abc@163.com",
 "phones": []
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM