Hi Adam,
That works for the first iteration, but I descend the tree like so:
bool enumpb( const char * pszpath, ENUMPROTOPROC f, const
google::protobuf::Descriptor * d, uintptr_t param ) {
std::string path = pszpath;
for ( int i = 0; i < d->field_count(); i++ ) {
auto field = d->field( i );
std::string localpath = pszpath;
if ( 0 != strcmp( "component", field->name().c_str() ) ) {
localpath.append( field->name() );
}
if ( ( ! localpath.empty() ) && ( '/' != localpath.back() ) ) {
if ( f && ! f( field, localpath.c_str(), param ) ) {
return false;
}
}
auto mt = field->message_type();
if ( ! mt ) {
continue;
} else if ( 0 != strcmp( d->full_name().c_str(),
mt->full_name().c_str() ) ) {
std::string localpath2 = localpath;
if ( ( ! localpath.empty() ) && ( '/' != localpath.back() ) ) {
localpath2.append( "/" );
}
if ( ! enumpb( hp, report, localpath2.c_str(), f, mt, param ) )
{
return false;
}
} else {
// printf( "Skipping circular %s" EOL, d->full_name().c_str() );
}
}
return true;
}
So I start the traversal like this:
auto d = report->GetDescriptor();
enumpb( "", f, d, param );
And it goes down the variable, visiting each leaf and nested child
variable, but I can't address each nested child directly that way, can I?
The mt variable does hold the descriptor for each nested variable at some
point, but I don't know how I'd derive the variable's instance from it.
On Tuesday, 22 June 2021 at 13:47:15 UTC-4 [email protected] wrote:
> I think the easiest thing would be that wherever you're now storing a
> google::protobuf::FieldDescriptor*, you can also store a
> google::protobuf::Message* pointing to the parent message.
>
> On Tue, Jun 22, 2021 at 10:41 AM J G <[email protected]> wrote:
>
>> 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
>>
>> <https://groups.google.com/d/msgid/protobuf/764459e6-6f37-42aa-869c-0f8405aa13c6n%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/3d9ed924-341b-43cf-8359-c91a93d1916dn%40googlegroups.com.