之前写了《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 << o |
关闭
站长推荐 /1
|