【问题标题】:Fill CapnProto List with non-primitive使用非原始填充 CapnProto 列表
【发布时间】:2018-03-19 22:53:34
【问题描述】:

根据 CapnProto 文档:(注意:我使用的是 C++ 版本)

对于 Foo 为非原始类型的 List,返回的类型为 operator[] 和 iterator::operator*() 是 Foo::Reader (对于 List::Reader)或 Foo::Builder(对于 List::Builder)。这 builder 的 set 方法将 Foo::Reader 作为其第二个参数。

虽然对非原始类型使用“set”似乎可以正常工作: Other stack overflow question for primitives only

对于自动生成的非原始列表似乎没有“设置”功能。我的 CapnProto 生成是否以某种方式失败,或者是否有另一种方法可以在非原始列表中设置元素?

【问题讨论】:

    标签: c++ capnproto


    【解决方案1】:

    有一个“set”的方法,不过叫setWithCaveats()

    destListBuilder.setWithCaveats(index, sourceStructReader)
    

    这是为了让您知道在设置结构列表的元素时存在一些晦涩难懂的问题。问题源于结构列表表示为您可能期望的指针列表,而是它们是一系列“扁平化”的连续结构,所有结构都具有相同的大小。这意味着列表中所有结构的空间都是在初始化列表时分配的。因此,当您调用setWithCaveats() 时,目标空间之前已经分配,​​并且您正在将源结构复制到该空间中。

    这在面对不同版本时提出了一个问题:源结构可能是使用更新版本的协议构建的,其中定义了额外的字段。在这种情况下,它实际上可能比预期的要大。但是,根据您编译的协议版本,目标空间已经分配。所以,太小了!不幸的是,我们别无选择,只能丢弃我们不知道的新定义的字段。因此,数据可能会丢失。

    当然,可能是在您的应用程序中,您知道结构值不是来自较新的版本,或者您不在乎是否丢失了您不知道的字段。在这种情况下,setWithCaveats() 会做你想做的事。

    如果您想小心保留未知字段,您可能需要查看方法capnp::Orphanage::newOrphanConcat()。此方法可以将结构读取器列表的列表连接到一个列表中,这样不会丢失任何数据——分配目标列表的每个结构的大小等于所有输入结构的最大值。

    auto orphanage = Orphanage::getForMessageContaining(builder);
    auto orphan = orphanage.newOrphanConcat({list1Reader, list2Reader});
    builder.adoptListField(kj::mv(orphan));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-10
      • 2019-11-06
      • 2018-11-01
      • 2019-07-18
      • 2021-08-02
      • 2011-02-05
      • 1970-01-01
      • 2013-06-15
      相关资源
      最近更新 更多