generic message editor? parse .proto files?

354 views
Skip to first unread message

David McClurg

unread,
Dec 1, 2009, 1:27:43 PM12/1/09
to Protocol Buffers
I'm trying to rebuild a message editor for a game engine using
protocol buffers. Currently we are using an XML template to describe
the message type and XML to store the message. I like the protocol
buffer language ( .proto files ) as well as the memory and performance
advantages over XML.

The tricky part is the message editor. The message editor tool needs
to...
1) parse all .proto files for the game
2) present the user with a input form for a selected message type
3) build a protocol message
4) save the message to disk for the game to load.

The property editor doesn't know about any message types at compile
time. The game knows about all message types at compile time. For
the message editor, message types need to be dynamically generated
from .proto files. For the game, messages are read from disk and used
to construct game objects and populate the world.

From other discussions, I've read this is possible but not obvious
with protocol buffers.

Could you please explain in specific terms how to parse a bunch
of .proto files from disk into message types at runtime? How do I
parse .proto files on-the-fly?

Thanks,
David

Peter Keen

unread,
Dec 1, 2009, 3:13:24 PM12/1/09
to David McClurg, Protocol Buffers
Is there a reason why you can't compile the message types into the
message editor? It seems like they're pretty intimately tied together
as it is.

--Pete
> --
>
> You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
> To post to this group, send email to prot...@googlegroups.com.
> To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.
>
>
>

Peter Keen

unread,
Dec 1, 2009, 3:15:14 PM12/1/09
to David McClurg, Protocol Buffers
Oh, that was just curiosity by the way. The real answer (in c++) is to
look at DescriptorPool, DescriptorDatabase, and DynamicMessage. I
started going down this path yesterday but it was taking too long to
figure out how it all goes together so I just wrote a quick and dirty
tool and compiled the message type in.

--Pete

David McClurg

unread,
Dec 1, 2009, 4:30:17 PM12/1/09
to Peter Keen, Protocol Buffers
That's true.  Adding a new type is like adding a new game feature.  Requiring a tool update for content people (non-programmers) might be acceptable.

I just thought that with reflection and the compiler parser, it would be a snap.

Thanks,
David

On Tue, Dec 1, 2009 at 12:13 PM, Peter Keen <peter...@gmail.com> wrote:

Kenton Varda

unread,
Dec 1, 2009, 4:34:16 PM12/1/09
to David McClurg, Protocol Buffers
To parse protos at runtime you will either need to use C++, or you will need to invoke protoc as a subprocess and have it output a FileDecsriptorSet which you can use in Java or other languages.  I'll assume C++.

Be sure to get familiar with the API documentation here:
There are basically two steps here:

(1) Parse the files to produce descriptors.  Descriptors (a family of classes defined in descriptor.h) are data structures representing parsed .proto files.  For this step, you want to use the Importer class found in importer.h.  Assuming your proto files are located on-disk, you'll want to give it a DiskSourceTree -- but you can provide your own SourceTree implementation if your files are located somewhere else.

(2) Use descriptors to construct DynamicMessages.  DynamicMessage is an implementation of the Message interface which mimics a type given by a descriptor.  Actually, the DynamicMessage class itself is private -- the class you will use is DynamicMessageFactory, defined in dynamic_message.h.  This is just a simple factory which takes a Descriptor and returns a default instance of that class.  You can then call New() on that default instance to construct a mutable instance.  The message can be modified via the Reflection interface as defined in message.h.

This may sound complicated but it actually comes down to only a few lines of code.

On Tue, Dec 1, 2009 at 10:27 AM, David McClurg <dave.m...@gmail.com> wrote:

David McClurg

unread,
Dec 1, 2009, 4:42:14 PM12/1/09
to Kenton Varda, Protocol Buffers
Thanks!  Any chance for a C++ code snippet?  Even an un-tested one would get me going in the right direction.

Kenton Varda

unread,
Dec 1, 2009, 4:55:44 PM12/1/09
to David McClurg, Protocol Buffers
using google::protobuf;

class MyErrorCollector : public protobuf::compiler::MultiFileErrorCollector {
  // Implementation of MultiFileErrorCollector interface.
  // Should probably just print errors to stderr.
};

// Set up the importer.
protobuf::compiler::DiskSourceTree source_tree;
source_tree.MapPath("", "path/to/src");
MyErrorCollector error_collector;
protobuf::compiler::Importer importer(&source_tree, &error_collector);

// Parse "path/to/src/foo/bar/baz.proto" and get the type "MyMessageType"
// defined within it.
const protobuf::FileDescriptor* file = importer.Import("foo/bar/baz.proto");
if (file == NULL) {
  // Error should have been reported to error_collector.
  return false;
}
const protobuf::Descriptor* type = file->FindMessageTypeByName("MyMessageType");
if (type == NULL) {
  cerr << "No such type: MyMessageType" << endl;
  return false;
}

// Get message prototype.
protobuf::DynamicMessageFactory factory;
const protobuf::Message* prototype = factory.GetPrototype(type);

// Make a message.
protobuf::Message* message = prototype->New();

// Let the user edit the message.  Uses reflection interface.
// See text_format.cc for an example of using reflection.
RunEditorUI(message);

// Serialize and write.
std::string data = message->SerializeAsString();
WriteData(data);
Reply all
Reply to author
Forward
0 new messages