7

I am trying to define a common basic message which defines the type of the message (for easier parsing) and is then extended with the actual message. The messages will be used in an RPC way.

My .proto file

syntax = "proto2";
package userapi;

// wrapper for commands
message Command
{
    // for "subclassing"
    extensions 100 to max;

    enum Type
    {
        Request = 1;
        Response = 2;
    }

    required Type type = 1;
}   

message Request
{
    // register this message type as extension to command
    extend Command
    {       
        optional Request command = 100;
    }

    optional string guid = 1;
}

message Response
{
    // register this message type as extension to command
    extend Command
    {       
        optional Response command = 101;
    }

    optional string guid = 1;

    //! error handling for command
    optional ErrorMsg error = 2;

    message ErrorMsg
    {
        enum ErrorCode
        {
            //! no error occured
            NONE = 0;
            //! the requested GUID already existed
            GUID_NOT_UNIQUE = 1;
        }

        optional string ErrorString = 1;
    }
}

Somewhat similar to this example, but i cant seem to set the extension value via

Command commandRequest;
commandRequest.set_type(Command_Type_Request);

auto extension = commandRequest.GetExtension(Request::command);
extension.set_guid("myGuid");

commandRequest.SetExtension(Request::command, extension);

The SetExtension() call fails with the following error message

error C2039: 'Set' : is not a member of 'google::protobuf::internal::MessageTypeTraits'

Unfortunately, this similar question does also not feature an example of the construction under c++.

Did i misunderstand the concept of extensions? What is a more clean way to establish this (and no, i dont want to serialize the command into a string).

I was following the examples under "nested extensions" in the documentation, which only sets basic types. I also tried to understand how rpcz solves this problem, but i failed, maybe some hints will help with this question?

Community
  • 1
  • 1
x29a
  • 1,761
  • 1
  • 24
  • 43
  • 1
    Just as an aside, extensions are not part of proto3 - so if you're looking to migrate your messages to proto3 in the future, you might want to reconsider using extensions. – Jon Skeet Jun 15 '15 at 16:51
  • Ok thanks, im also open for a proto3 solution! I guess defining lots of optional fields would be one? :/ Similiar to [this](https://stackoverflow.com/questions/6243362/how-to-use-extensions-from-protocol-buffers-to-maintain-general-message) – x29a Jun 15 '15 at 16:55
  • You might want to look at the `Any` type, or possibly a `oneof`. There are lots of different options here, depending on your exact requirements. – Jon Skeet Jun 15 '15 at 17:00

1 Answers1

10

Extensions are a lot like regular fields. For primitive fields, you get accessors to get and set the field. For sub-messages, though, you don't get a "set" accessor -- you get "get" and "mutable", just like you would for a regular submessage field. So, you want:

Request* request =
    commandRequest.MutableExtension(Request::command);
request->set_guid("myGuid");
Kenton Varda
  • 41,353
  • 8
  • 121
  • 105
  • with the second argument to MutableExtension() the code does not compile, is that intended and needed? – x29a Jun 17 '15 at 13:46
  • 1
    @x29a It was a copy-paste error. Your edit was correct. Sadly it seems moderators rejected your edit. I've updated the post directly. Thanks. – Kenton Varda Jun 17 '15 at 17:38