1

I'm struggling a bit in understanding how to properly encode/decode strings in a protobuf message using nanopb. The message to encode/decode looks something like this:

struct CDAPMessage {
//...
    optional string objName    = 6; // Object name, unique in its class
    optional int64 objInst     = 7; // Unique object instance
//...
}

The message has more fields, but they are all the same type (either optional string or optional int).

Once compiled, in the .pb.h file, I have

typedef struct _CDAPMessage {
//...
    pb_callback_t objName;  /* Object name, unique in its class */
    bool has_objInst;
    int64_t objInst; /* Unique object instance */
//...
}

I would like to have a function to decode the whole message, something like that:

CDAPMessage *
cdap_decode_msg(void *buf, size_t msg_len)
{ 
    // Allocate space for the decoded message
    CDAPMessage msg = CDAPMessage_init_zero;

    // Create a stream that reads from the buffer.
    pb_istream_t stream = pb_istream_from_buffer(buf, msg_len);

    /* Now we are ready to decode the message. */
    bool status = pb_decode(&stream, CDAPMessage_fields, &msg);

    // Check for errors...
    if (!status) {
        error("Decoding failed: %s\n", PB_GET_ERROR(&stream));
        return NULL; // Returning empty message
    }
    return CDAPMessage;
}

However, with this method I have no problem to encode integers, but it does not work for encoding strings (it does not complain, just does not encode anything). I guess it is because I should use some sort of function pointer in the pb_callback_t struct for encode/decode, as well as having the string value in the args field.

I can't really find a good example that does what I want, and official documentation is a bit though for me, and I can't really take something in clear from it. So any help pointing to the right direction would be appreciated.

  • You'll probably want to define field option such as `[(nanopb).max_size = 50]` on the string field to get it allocated as a char array. – jpa Sep 22 '21 at 17:25
  • That's actually an easy workaround and may be ok for my use case. Thanks for the suggestion :) – Sergio Giménez Sep 22 '21 at 17:43

1 Answers1

1

As you mentioned, you'll need to implement a callback mechanism.
Now, as @jpa suggested, if you can have a known max len, you can specify that option so that you can get it as a char array. Otherwise, you will need a callback.
For an example of the callback, see https://github.com/nanopb/nanopb/blob/master/tests/callbacks/decode_callbacks.c
There is an example there of how to write the callback , how to attach the function pointer and then how to decode the message.

kalyanswaroop
  • 403
  • 4
  • 5
  • Thanks for the link. I'll take a look. However, I will probably go for the char array approach since might be ok for my use case – Sergio Giménez Sep 22 '21 at 17:44