Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

protocol buffers cpp embedded message

My .proto file looks like

message Cmd
{
      int code =  1;
}

message CmdOne
{
      required Cmd cmd = 1;
      required int data = 2;
}

message CmdTwo
{
      required Cmd cmd = 1;
      required string data = 2;
}

In my cpp file, I want to declare objects of CmdOne and CmdTwo and set both cmd and data members. But the generated pb.h file does not have a set method for the cmd member of CmdOne and CmdTwo objects, but has a set method for the data member. How do I set the value of cmd for each object?

I don't want to define message Cmd inside CmdOne and CmdTwo messages. I want to reuse the Cmd message as I have 10 messages CmdOne to CmdTen.

like image 674
Nani Avatar asked Dec 05 '13 08:12

Nani


1 Answers

You have a couple of different options. You can get a non-const pointer to the cmd field, and then allocate value(s) appropriately:

CmdOne cmd_one;
Cmd* cmd(cmd_one.mutable_cmd());
cmd->set_code(2);
// Previous 2 lines could be simplified to:
// cmd_one.mutable_cmd()->set_code(2);

Alternativey, if you want to pass a constructed instance of Cmd into CmdOne, you can do:

Cmd* cmd(new Cmd);
cmd->set_code(1);

CmdOne cmd_one;
cmd_one.set_allocated_cmd(cmd);  // Takes ownership of cmd -
                                 // you don't call 'delete cmd'

From the "Singular Embedded Message Fields" section of the docs:

Given the message type:

message Bar {}

For either of these field definitions:

optional Bar foo = 1;
required Bar foo = 1;

The compiler will generate the following accessor methods:

...

Bar* mutable_foo()

Returns a mutable pointer to the Bar object that stores the field's value. If the field was not set prior to the call, then the returned Bar will have none of its fields set (i.e. it will be identical to a newly-allocated Bar). After calling this, has_foo() will return true and foo() will return a reference to the same instance of Bar. The pointer is invalidated by a call to Clear() or clear_foo().

...

void set_allocated_foo(Bar* bar)

Sets the Bar object to the field and frees the previous field value if it exists. If the Bar pointer is not NULL, the message takes ownership of the allocated Bar object and has_foo() will return true. Otherwise, if the Bar is NULL, the behavior is the same as calling clear_foo().

like image 200
Fraser Avatar answered Oct 22 '22 00:10

Fraser