Как динамически строить новый protobuf из набора уже определенных дескрипторов?

На моем сервере мы получаем самоописанные сообщения (как определено здесь... что было не так просто, как там aren ' t любые "хорошие" примеры этого в С++).

В этот момент у меня нет проблем с созданием сообщений из этих самоописанных. Я могу взять FileDescriptorSet, пройти через FileDescriptorProto, добавив каждый в DescriptorPool (используя BuildFile, который также дает мне каждый определенный FileDescriptor).

Отсюда я могу создать любое из сообщений, которые были определены в FileDescriptorSet, с DynamicMessageFactory, созданным с помощью DP и вызывающим GetPrototype ( что очень легко сделать, так как наш SelfDescribedMessage требует сообщений full_name(), и поэтому мы можем вызвать метод FindMessageTypeByName, дающий нам правильно закодированный прототип сообщения).

Вопрос в том, как я могу взять каждый уже определенный дескриптор или сообщение и динамически создавать сообщение "master", которое содержит все определенные сообщения в виде вложенных сообщений. Это будет в первую очередь использоваться для сохранения текущего состояния сообщений. В настоящее время мы справляемся с этим, просто создавая тип каждого сообщения на сервере (чтобы сохранить центральное состояние в разных программах). Но когда мы хотим "сэкономить" текущее состояние, мы вынуждены передавать их на диск, как указано здесь. Они передаются по одному сообщению за раз (с префиксом размера). Мы хотели бы иметь сообщение ONE (одно правило для всех) вместо постоянного потока отдельных сообщений. Это можно использовать для других вещей после его разработки (сетевое разделенное состояние с оптимизированной и простой сериализацией)

Поскольку у нас уже есть сшитые и определенные дескрипторы, можно подумать, что будет простой способ создания "новых" сообщений из уже определенных. До сих пор решение намекало нам. Мы попытались создать наш собственный DescriptorProto и добавить новые поля типа из наших уже определенных дескрипторов, но потерялись (еще не погрузились в это). Мы также рассмотрели возможность добавления их в качестве расширений (пока неизвестно, как это сделать). Нужно ли создавать собственный DescriptorDatabase (также неизвестно в это время, как это сделать)?

Любые идеи?


Связано пример источника в BitBucket.


Надеюсь, это объяснение поможет.

Я пытаюсь динамически создавать сообщение из набора уже определенных сообщений. Набор уже определенных сообщений создается с использованием метода "самоописанного", который объясняется (кратко) в официальном учебном пособии по программированию С++ (т.е. Эти сообщения недоступны в скомпилированной форме). Это новое определенное сообщение нужно будет создать во время выполнения.

Попробовали использовать прямые дескрипторы для каждого сообщения и попытались создать FileDescriptorProto. Попробовали посмотреть методы DatabaseDescriptor. Оба не повезло. В настоящее время попытка добавления этих определенных сообщений в качестве расширения к другому сообщению (даже во время компиляции эти определенные сообщения и их "набор дескрипторов" не были классифицированы как расширение чего-либо), в котором начинается код примера.

26
17 авг. '12 в 1:52
источник поделиться
3 ответов

Я смог решить эту проблему, динамически создав файл .proto и загрузив его Importer.

Единственное требование заключается в том, чтобы каждый клиент либо отправлял через свой прото файл (только в init... не во время полного выполнения). Затем сервер сохраняет каждый прото файл в каталог temp. Альтернативой, если это возможно, является просто указание сервера на центральное место, где хранятся все необходимые прото файлы.

Это было сделано сначала с использованием DiskSourceTree для сопоставления фактических мест пути в виртуальных программах. Затем создайте файл .proto для импорта каждого прото файла, который был отправлен через AND, и укажите необязательное поле в "главном сообщении".

После того, как master.proto был сохранен на диск, я импортирую его с помощью Импортера. Теперь, используя Importers DescriptorPool и DynamicMessageFactory, я могу надежно генерировать все сообщение под одним сообщением. Я буду приводить пример того, что я описываю позже сегодня или завтра.

Если у кого-то есть предложения о том, как сделать этот процесс лучше или как это сделать, скажите об этом.

Я оставлю этот вопрос без ответа до тех пор, пока щедрость не истечет, если у кого-то есть лучшее решение.

4
22 авг. '12 в 21:09
источник

вам понадобится protobuf::DynamicMessageFactory:

{
  using namespace google;

  protobuf::DynamicMessageFactory dmf;
  protobuf::Message* actual_msg = dmf.GetPrototype(some_desc)->New();

  const protobuf::Reflection* refl = actual_msg->GetReflection();

  const protobuf::FieldDescriptor* fd = trip_desc->FindFieldByName("someField");
  refl->SetString(actual_msg, fd, "whee");

  ... 

  cout << actual_msg->DebugString() << endl;
}
5
17 апр. '14 в 4:17
источник

Как насчет сериализации всех сообщений в строках и создания главного сообщения последовательности (байтовых) строк, a la

message MessageSet
{
  required FileDescriptorSet proto_files = 1;
  repeated bytes serialized_sub_message = 2;
}
1
22 авг. '12 в 17:16
источник

Посмотрите другие вопросы по меткам или Задайте вопрос