在我的服务器上,我们收到自我描述的消息(定义为here ...顺便说一句,因为在c ++中没有任何'好'的例子)。
此时我从这些自我描述的消息中创建消息没有任何问题。我可以使用FileDescriptorSet,遍历每个FileDescriptorProto,将每个添加到DescriptorPool(使用BuildFile,这也为我提供了每个定义的FileDescriptor)。
从这里我可以创建在FileDescriptorSet中定义的任何消息,其中DynamicMessageFactory与DP一起实例并调用GetPrototype(这很容易做到,因为我们的SelfDescribedMessage需要消息full_name(),因此我们可以调用DP的FindMessageTypeByName方法,为我们提供正确编码的Message Prototype。)
问题是如何获取每个已定义的描述符或消息,并动态构建包含所有已定义消息的“主”消息作为嵌套消息。这主要用于保存消息的当前状态。目前我们只是通过实例化服务器中每种消息的类型来处理这个问题(以保持不同程序的中心状态)。但是当我们想要“保存”当前状态时,我们不得不按照定义的here将它们传输到磁盘。它们一次流式传输一条消息(带有大小前缀)。我们希望有一条消息(一条用于统治所有消息)而不是单独消息的稳定流。一旦解决了这个问题,它就可以用于其他事情(基于网络的共享状态,优化和简单的序列化)
由于我们已经有了交叉链接和定义的描述符,人们会认为有一种简单的方法可以从那些已定义的消息中构建“新”消息。到目前为止,解决方案已经提到了我们。我们已经尝试创建我们自己的DescriptorProto并从已经定义的描述符中添加该类型的新字段但是迷路了(还没有深入研究这个)。我们还看过可能会将它们添加为扩展名(目前未知如何)。我们是否需要创建自己的DescriptorDatabase(目前还不知道该怎么做)?
任何见解?
在BitBucket上链接example source。
希望这个解释会有所帮助。
我正在尝试从一组已定义的消息中动态构建消息。已经定义的消息集是通过使用官方c ++ protobuf教程中(简要地)解释的“自描述”方法创建的(即这些消息不以编译形式提供)。需要在运行时创建此新定义的消息。
尝试为每条消息使用直接描述符并尝试构建FileDescriptorProto。试过看过DatabaseDescriptor方法。两个都没有运气。目前正在尝试将这些定义的消息添加为另一条消息的扩展(即使在编译时这些定义的消息,以及它们的'描述符集'也没有被分类为扩展任何内容),这是示例代码开始的地方。
答案 0 :(得分:6)
您需要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;
}
答案 1 :(得分:4)
我能够通过动态创建.proto文件并使用Importer加载来解决此问题。
唯一的要求是每个客户端要么跨原始文件发送(仅在初始化时需要...而不是在完全执行期间)。然后,服务器将每个proto文件保存到临时目录。如果可能,另一种方法是将服务器指向一个包含所有所需原型文件的中心位置。
这是通过首先使用DiskSourceTree将实际路径位置映射到程序虚拟路径位置来完成的。然后构建.proto文件以导入跨越发送的每个proto文件并在“主消息”中定义可选字段。
将master.proto
保存到磁盘后,我使用导入程序导入它。现在使用Importers DescriptorPool和DynamicMessageFactory,我能够在一条消息下可靠地生成整个消息。我将在今晚或明天稍后举例说明我所描述的内容。
如果有人对如何更好地完成此过程或如何做到这一点有任何建议,请说明。
我将不再回答这个问题,直到赏金即将到期,以防其他人有更好的解决方案。
答案 2 :(得分:1)
如何将所有消息序列化为字符串,并使主消息成为(字节)字符串序列,la
message MessageSet
{
required FileDescriptorSet proto_files = 1;
repeated bytes serialized_sub_message = 2;
}