【问题标题】:How to access serialized data of Cap'n'Proto?如何访问 Cap'n'Proto 的序列化数据?
【发布时间】:2021-06-23 19:35:14
【问题描述】:

我正在使用 Cap'n'Proto,我的理解是没有必要进行序列化,因为它已经完成了。所以我的问题是,我将如何访问序列化数据并获取它的大小,以便我可以将它作为字节数组传递给另一个库。

// person.capnp
struct Person {
    name @0 :Text;
    age @1 :Int16;
}

// ...
::capnp::MallocMessageBuilder message;

Person::Builder person = message.initRoot<Person>();
person.setName("me");
person.setAge(20);

// at this point, how do I get some sort of handle to 
// the serialized data of 'person' as well as it's size?

我看到了writePackedMessageToFd(fd, message); 调用,但不太了解传递的内容,也找不到任何 API 文档。我也没有尝试写入文件描述符,因为我需要以const void* 返回的序列化数据。

在 Capnproto 的 message.h 文件中查看此函数,它位于 MallocMessageBuilder 的基类中,表示它获取构成消息的原始数据。

kj::ArrayPtr<const kj::ArrayPtr<const word>> getSegmentsForOutput();
// Get the raw data that makes up the message.

但即便如此,我也不知道如何将其设为const void*

想法?

【问题讨论】:

    标签: c++ protocol-buffers capnproto


    【解决方案1】:
    ::capnp::MallocMessageBuilder message;
    

    是你的二进制消息,它的大小是

    message.sizeInWords()
    

    (字节大小除以 8)。

    【讨论】:

    • 我试了一下,事情就搞砸了。试图弄清楚返回的是什么。将继续使用它。
    【解决方案2】:

    这似乎是需要的。

    // ...
    ::capnp::MallocMessageBuilder message;
    
    Person::Builder person = message.initRoot<Person>();
    person.setName("me");
    person.setAge(20);
    
    kj::Array<capnp::word> dataArr = capnp::messageToFlatArray(message);
    kj::ArrayPtr<kj::byte> bytes = dataArr.asBytes();
    
    std::string data(bytes.begin(), bytes.end());
    
    const void* dataPtr = data.c_str();
    

    此时,我有一个const void* dataPtr 和使用data.size() 的大小。

    【讨论】:

    • 显然问题在于无线表示包含多个“段”,您不能将它们连接在一起 - 开头有一些元数据。请参阅here messageToFlatArray 获取这些段(即使只有一个,我猜),然后调用 here 将它们粘合到缓冲区中。
    • (我猜这意味着额外的副本是不可避免的,除非您只是复制 writeMessage 的功能以将其复制到您真正想要的位置。)
    • 谢谢。我必须尝试了解我是否获得了所有细分,或者我是否需要做更多的事情,因为我已经在使用messageToFlatArray。我也会调查writeMessage。我只需要将const void* 交给另一个图书馆。
    • messageToFlatArray 本身将 all 段复制到缓冲区,然后将缓冲区交还给您。但它首先将段数 - 1 粘贴在该缓冲区的前面(我想反序列化器知道它需要反序列化多少段)。
    • 顺便说一句,除非您迫切希望字符串添加到缓冲区末尾的尾随 \0 字符,否则您将返回 c_str() - 考虑 not i> 将缓冲区从kj::Array dataArr 中复制出来,而不是直接与kj::Array::asBytes()kj::Array::asChars() 一起使用,或者甚至,如果您想从kj::Array 中获取缓冲区的所有权,请使用kj::Array::releaseAsBytes/Chars() .如果这对您很重要,请每次保存一份缓冲区副本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    相关资源
    最近更新 更多