Hi Adam, Yes, the HealthReport variable is the parent, and it contains a HardwareComponent variable, but I am enumerating the from the parent, meaning I am trying to not hard-code the structure of the contained items.
So how would I obtain a pointer to the message for each leaf without hard-coding the member names in there? I am able to figure out what value I want to set in each leaf by a map I have that uses the field's path to match it to the value I want to store. On Tuesday, 22 June 2021 at 13:33:11 UTC-4 [email protected] wrote: > 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/764459e6-6f37-42aa-869c-0f8405aa13c6n%40googlegroups.com.
