nanopb oneof 尺寸要求

Posted

技术标签:

【中文标题】nanopb oneof 尺寸要求【英文标题】:nanopb oneof size requirements 【发布时间】:2019-05-22 13:12:16 【问题描述】:

我遇到了 nanopb,想在我的项目中使用它。我正在为嵌入式设备编写代码,因此内存限制是一个真正的问题。

我的目标是在设备之间传输数据项,每个数据项都有一个 32 位标识符和一个值。该值可以是从 1 个字符到浮点数到长字符串的任何值。我想知道为此类问题声明消息的最有效方法是什么。

我在想这样的事情:

message data_msg
    message data_item
        int32 id = 1;
        oneof value
            int8  ival = 2;
            float fval = 3;
            string sval = 4;
        
    
  repeated data_item;

但据我了解,这被转换为 C 联合,即最大元素的大小。假设我将字符串限制为 50 个字符,那么联合始终是 50 个字节长,即使我需要 4 个字节作为浮点数。

我是否正确理解了这一点,还是有其他方法可以做到这一点?

谢谢!

【问题讨论】:

【参考方案1】:

您的理解是正确的,C 中的结构大小将等于 oneof 中最大成员的大小。但这只是内存中的大小,序列化后的消息大小将是内容所需的最小值。

如果内存大小是个问题,有几个选项可用。分配可能需要的最大大小的默认设置使内存管理变得容易。如果您只想动态分配所需的内存量,则必须决定如何进行:

    使用PB_ENABLE_MALLOC 编译选项,您可以将FT_POINTER 字段类型用于字符串和其他大字段。然后将使用系统堆中的malloc() 分配内存。

    使用FT_CALLBACK,您将获得一个回调,而不是分配任何内存,您可以在其中读出字符串并以任何您想要的方式处理或存储它。例如,如果您想将字符串写入 SD 卡,则无需将其完全存储在内存中即可。

在整体系统设计中,针对所需最大大小的静态分配通常是最容易测试的。如果数据适合一次,它将始终适合。如果您选择动态分配,则需要更仔细地分析可能需要的最大内存使用量。

【讨论】:

如果我只使用一堆可选字段而不是其中一个呢?我认为序列化后没关系,但在内存中,每个 data_item 占用空间的不必要的空指针很少吗? @OuTsei 默认情况下,可选字段也直接分配在结构中。如果它们是配置的指针(类型 = FT_POINTER),则意味着内存是单独分配的,如本答案中所述。 所以也许可以为所有类型的数据(浮点数、整数字符串等)设置单独的 data_item 规范,并为所有这些单独设置重复的结构? @OuTsei 如果该重复结构的大小不是恒定的,您将在哪里获得内存?它总是以静态分配最大大小或动态分配而告终。您可以通过多种方式构建动态分配,但不会改变其基本属性,例如更难的测试。

以上是关于nanopb oneof 尺寸要求的主要内容,如果未能解决你的问题,请参考以下文章

无论如何,图标尺寸都不符合尺寸要求

MonoTouch 项目导致 Application Loader 错误消息“图标尺寸 (0 x 0) 不符合尺寸要求”

有啥方法可以创建密钥大小为 512 的 JWT 令牌?并更改 AsymmetricSignatureProvider 的默认最小尺寸要求

如何使用 nanopb 编译 .proto + .options 文件

无法构建模块“nanopb”

nanopb的使用