Rbdm
Rbdm

Reputation: 39

C++, Protobuf can't recognize other protos as fields

I'm using C++ and Protobuffer 3.19.1. I'm using this version specifically because I still occasionally use the "optional" fields.

I have the following .proto example file:

syntax = "proto3";

message PCollect {
  string site = 1;
  string id = 2;
  int64 ts = 3;
  optional PUser user = 4;
  optional PItem item = 5;
}

message PUser {
  int64 ts = 1;
  string name = 2;
  int64 num = 3;
  optional int64 opt = 4;
}

message PItem {
  int64 ts = 1;
  string name = 2;
  double price = 3;
  double size = 4;
  optional string id = 5;
}

In my C++ code I have a function where I receive as input either a PUser or PData message, I want to include said message in a PCollect proto, and save that to binary. Each PCollect instance is gonna have only 1 of the 2 fields. In my function I do:

PCollect append(const std::string site, const std::string id, const PUser user) {
    PCollect data;
    data.set_site(site);
    data.set_id(id);
    data.set_ts(user.ts());
    data.set_user(user);
    return data;
}

I have another identical function with PItem instead of PUser. When I try to compile, it compiles the proto correctly, but when it compiles C++ I get this error:

collector.h:47:12: error: ‘class PCollect’ has no member named ‘set_user’; did you mean ‘has_user’?

I get the same error for the other function trying to use PItem. It's not my first time using this design pattern and including protos inside other protos, so I can't understand why I'm getting this error. I tried cleaning out and re-compiling my protos only, but I wasn't able to get it to work. I also tried putting PCollect below the other 2 structs in the .proto file but nothing changed.

Upvotes: 0

Views: 608

Answers (1)

zpc
zpc

Reputation: 47

For cases Embedded Message Fields
Protobuf is not generating the setter as set_yourfield(), instead of is YourField* mutable_yourfield() and set_allocated_yourfield(YourField*)

With YourField* mutable_yourfield(), an instance will be initialized, and return a direct pointer. You can use this pointer as a setter. Example:

auto user_ = data.mutable_user();
user_->set_num(6);

With set_allocated_yourfield(YourField*), you must create an instance of YourFiled pointer, then set it for the message.
If the pointer is not null, the message takes ownership of the allocated, so you don't need to thinking freeing memory. Example:

PUser* user_ = new PUser;
data.set_allocated_user(user_);
user_->set_num(0);

Refer to this tutorial to get more information.

Upvotes: 2

Related Questions