Search code examples
cprotocol-buffersnanopb

Encoding/decoding optional string fields using nanopb


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.


Solution

  • 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.