Cap'n Proto C++ 序列化为 char 数组(或任何字节数组)

Cap’n Proto C++ serialize to char array (or any byte array)

我的目标是通过 MPI 发送序列化数据。我已经使用 ProtoBuf 完成了此操作,但我想尝试使用更快的序列化方法,例如 Cap'n Proto(我也会尝试其他方法,但在这里我被卡住了)。对于 ProtoBuf,我使用函数 SerializeToArray(void * data, int size) 函数,它工作得很好。

现在,我想用 Cap'n Proto 做同样的事情,但我找不到任何方法(如果你有 link 请发送)。由于 Cap'n Proto 声称是 ProtoBuf 的更快替代品,我觉得这令人惊讶。也许,我正在以完全错误的方式解决这个问题。

所以我的问题变成了:

如何使用 Cap'n Proto 序列化为 char 数组(或任何字节数组)(如果可能的话)?或者我如何以一种可以使用 C++ 通过 MPI 轻松发送的方式进行序列化?

我不确定这是否是最有效的方法,但它确实有效。

messages.capnp 文件:

@0xf46c6bd8234dfab9;

struct Testmessage {
  string @0 :Text;
  float @1 :Float32;
  int @2 :Int32;
}

run_cap_n_proto.cpp 文件:

#include <iostream>
#include <capnp/serialize.h>
#include "messages.capnp.h"

int main()
{
    // Encode message
    ::capnp::MallocMessageBuilder message_builder;
    Testmessage::Builder message = message_builder.initRoot<Testmessage>();

    message.setString( "string" );
    message.setFloat( 3.14 );
    message.setInt( 1337 );

    auto encoded_array = capnp::messageToFlatArray(message_builder);
    auto encoded_array_ptr = encoded_array.asChars();
    auto encoded_char_array = encoded_array_ptr.begin();
    auto size = encoded_array_ptr.size();

    // Send message
    // Receive message

    // Decode message
    auto received_array = kj::ArrayPtr<capnp::word>(reinterpret_cast<capnp::word*>(encoded_char_array), size/sizeof(capnp::word));
    ::capnp::FlatArrayMessageReader message_receiver_builder(received_array);
    auto message_receiver = message_receiver_builder.getRoot<Testmessage>();
    auto s_r = message_receiver.getString().cStr();
    auto f_r = message_receiver.getFloat();
    auto i_r = message_receiver.getInt();

    std::cout << "received: " << s_r << ", " << f_r << ", " << i_r << std::endl;
}

编译messages.capnp:

$ capnp compile -oc++ messages.capnp

编译主程序:

$ g++ -o run_cap_n_proto run_cap_n_proto.cpp messages.capnp.c++ `pkg-config --cflags --libs capnp`

对于文档中 AddrssBook example 中给出的消息,您可以这样做:

// Documentation: https://capnproto.org/cxx.html
// AddressBook example

void sendMessage( const char* data, const std::size_t size ); 

void writeAddressBook()
{
    ::capnp::MallocMessageBuilder message;

    auto addressBook = message.initRoot<AddressBook>();
    auto people = addressBook.initPeople(1);

    auto alice = people[0];
    alice.setId(123);
    alice.setName("Alice");
    alice.setEmail("alice@example.com");

    auto alicePhones = alice.initPhones(1);
    alicePhones[0].setNumber("555-1212");
    alicePhones[0].setType(Person::PhoneNumber::Type::MOBILE);
    alice.getEmployment().setSchool("MIT");

    // get char array and send

    const auto m = capnp::messageToFlatArray( message );
    const auto c = m.asChars();
    std::cout << c.size() << '\n';

    sendMessage( c.begin(), c.size() ); // pass as char array
}