So is it correct that HealthReport is the top-level message type and HardwareComponent is nested somewhere within that? I think what you're trying to do is doable, but when you call reflection->SetString(), you have to pass the immediate parent message containing the field, not the top-level message. You don't need to save the descriptor for each leaf, but you do need to save a pointer to the message containing each leaf.
On Tue, Jun 22, 2021 at 10:17 AM J G <[email protected]> wrote: > Hi again Adam, and thank you for taking the time to help me. > > Maybe I haven't explained what I am trying to do properly. > > I have a protobuf variable, which itself is composed of more nested > variables. > > I am enumerating the fields of the variable. > > Where the item is a leaf, the field is a simple c-like type (int, bool, > string, etc) > > Where the item itself has fields, it is an agglomerate type and it is > descended recursively. > > My aim is to set each leaf programmatically. > > So as I traverse the arborescance, I am collecting the field definitions > for the leafs. > > So later, I am addressing the variable again, but trying to set one of its > leafs by the field definition I saved. Do I also have to save the > descriptor for each leaf? > > Can what I want to do be done? > > > On Tuesday, 22 June 2021 at 11:52:00 UTC-4 [email protected] wrote: > >> It looks to me like r->report points to a vafmsg.HealthReport but the >> field descriptor refers to a field in another message >> (vafmsg.HardwareComponent). >> >> On Tue, Jun 22, 2021 at 7:42 AM J G <[email protected]> wrote: >> >>> Hello Adam, >>> >>> OK, I understand, so I've tried this, but I get an error. >>> >>> void my_set_value( class healthreport * r, const char * defaultvalue, >>> const google::protobuf::FieldDescriptor * descriptor ) { >>> >>> auto reflection = r->report->GetReflection(); >>> >>> switch( descriptor->type() ) { >>> case google::protobuf::FieldDescriptor::TYPE_STRING: { >>> >>> printf( "REQUESTED TYPE: STRING" EOL ); >>> std::string s = defaultvalue; >>> reflection->SetString( r->report, descriptor, s ); >>> >>> } >>> break; >>> >>> default: >>> >>> printf( "REQUESTED TYPE %d NOT HANDLED" EOL, >>> descriptor->type() ); >>> break; >>> >>> } >>> >>> } >>> Running the above produces the following output: >>> >>> REQUESTED TYPE: STRING >>> [libprotobuf FATAL >>> /var/tmp/portage/dev-libs/protobuf-3.15.8/work/protobuf-3.15.8/src/google/protobuf/generated_message_reflection.cc:111] >>> Protocol Buffer reflection usage error: >>> Method : google::protobuf::Reflection::SetString >>> Message type: vafmsg.HealthReport >>> Field : vafmsg.HardwareComponent.hardware_interface >>> Problem : Field does not match message type. >>> terminate called after throwing an instance of >>> 'google::protobuf::FatalException' >>> what(): Protocol Buffer reflection usage error: >>> Method : google::protobuf::Reflection::SetString >>> Message type: vafmsg.HealthReport >>> Field : vafmsg.HardwareComponent.hardware_interface >>> Problem : Field does not match message type. >>> >>> Here is the proto definition of the variable triggering the exception: >>> >>> message HardwareComponent { >>> optional Component component = 1; >>> repeated DiscreteValue temp = 2; >>> optional string hardware_interface = 3; >>> optional uint32 remaining_life = 4; >>> optional uint32 total_hours = 5; >>> optional EnergyInfo energy = 6; >>> } >>> >>> So the type really IS string, yet an exception is triggered... >>> >>> What am I doing wrong? >>> >>> On Friday, 18 June 2021 at 17:56:57 UTC-4 [email protected] wrote: >>> >>>> Each descriptor describes part of the schema (e.g. a message type, enum >>>> type, etc.) but is unrelated to any particular instance of it. As a result, >>>> if you have a descriptor by itself then you can't really modify anything >>>> because you separately need an instance of the thing you want to modify. >>>> The way to programmatically modify a message is to use the Reflection >>>> <https://github.com/protocolbuffers/protobuf/blob/9d9d8ee18dedfb18371031cd299d1d282ddf707f/src/google/protobuf/message.h#L452> >>>> API. You can use Reflection::ListFields() to get a list of all the fields >>>> that are set on the message and then there are Reflection::Get* and >>>> Reflection::Set* methods to get and set particular fields. >>>> >>>> On Fri, Jun 18, 2021 at 9:11 AM J G <[email protected]> wrote: >>>> >>>>> Hi, >>>>> >>>>> I've got some code that lets me recursively walk a protobuf variable. >>>>> >>>>> That part works, I can enumerate the characteristics of a variable, >>>>> but the pointers/references returned by the API are const. >>>>> >>>>> My question is: From a variable's Descriptor or FieldDescriptor, is it >>>>> possible to get a non-const pointer/reference to the field to be able to >>>>> modify it? >>>>> >>>>> Here's my (simplified) code so far: >>>>> >>>>> void enumpb( const google::protobuf::Descriptor * d ) { >>>>> >>>>> for ( int i = 0; i < d->field_count(); i++ ) { >>>>> >>>>> auto field = d->field( i ); >>>>> >>>>> // Modify variable code here >>>>> [...] >>>>> >>>>> auto mt = field->message_type(); >>>>> if ( ! mt ) { >>>>> continue; >>>>> } else if ( 0 != strcmp( d->full_name().c_str(), >>>>> mt->full_name().c_str() ) ) { >>>>> >>>>> enumpb( mt ) ; >>>>> >>>>> } >>>>> >>>>> } >>>>> >>>>> return true; >>>>> >>>>> } >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Protocol Buffers" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/protobuf/dcf6bb53-24ce-4404-ab71-0fe3a94adc40n%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/protobuf/dcf6bb53-24ce-4404-ab71-0fe3a94adc40n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Protocol Buffers" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/protobuf/7ef6e77e-8635-4b16-b570-b80f75d207d9n%40googlegroups.com >>> <https://groups.google.com/d/msgid/protobuf/7ef6e77e-8635-4b16-b570-b80f75d207d9n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google Groups > "Protocol Buffers" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/protobuf/39fd7a89-426a-453d-9482-4cb3e3658da0n%40googlegroups.com > <https://groups.google.com/d/msgid/protobuf/39fd7a89-426a-453d-9482-4cb3e3658da0n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/protobuf/CADqAXr44-1mrg-xsrfRGb4g9QJt5Hg_M5nJq041-dZeJGu691A%40mail.gmail.com.
