1

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

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

虽然使用“set”似乎适用于非原始类型: Other stack overflow question for primitives only

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

4

1 回答 1

1

有一个“设置”方法,但它被称为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));
于 2018-03-20T21:01:24.797 回答