字符串为pb_callback_t类型时如何编码

时间:2019-08-20 08:29:45

标签: c protocol-buffers nanopb

我正在使用Nanopb,将生成的原始文件中的字符串变量转换为pb_callback_t

因此,到目前为止,我正在尝试使用nanopb回调的测试示例;

bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
    char str[14] = "Hello world!";

    if (!pb_encode_tag_for_field(stream, field))
        return false;

    return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
int main()
{
FeatureFile featurefile = FeatureFile_init_zero;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));

featurefile.features.Id.funcs.encode = &encode_string;
}

但是在此示例中,字符串“ Hello world!”是非常硬编码的xD,该如何从main动态地将字符串传递给该函数?

1 个答案:

答案 0 :(得分:2)

pb_callback_t结构包含一个void* arg字段,您可以使用该字段通过arg参数将任何自定义数据传递给编码/解码功能。

在这种情况下,您可以这样做:

int main()
{
    ... 
    featurefile.features.Id.arg = "something";
    featurefile.features.Id.funcs.encode = &encode_string;
}

请注意,arg参数是void * const指针,因此您将始终必须取消引用它:

bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
    const char* str = (const char*)(*arg);

    if (!pb_encode_tag_for_field(stream, field))
        return false;

    return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}

请注意,您可以将指针传递给任何结构,即,您可以轻松创建一种“解析上下文”结构并将其传递给周围环境,这样您就不必关心解析函数将如何使用它。 / p>

在这种情况下,可能是这样的:

typedef struct
{
    const char * something;
    const char * whatever;
    ...
}
callback_context_t;

int main()
{
    callback_context_t ctx = { .something = "something" };

    // this way you always pass the same pointer type
    featurefile.features.Id.arg = &ctx;
    featurefile.features.Id.funcs.encode = &encode_string;
}

bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
    // ...and you always cast to the same pointer type, reducing
    // the chance of mistakes
    callback_context_t * ctx = (callback_context_t *)(*arg);

    if (!pb_encode_tag_for_field(stream, field))
        return false;

    return pb_encode_string(stream, (uint8_t*)ctx->something, strlen(ctx->something));
}