Ответ 1
IIUC, вы хотите записать в предварительно выделенный массив фиксированного размера.
Вы можете использовать boost:: iostreams:: array_sink (завернутый stream, чтобы предоставить ему интерфейс std:: ostream).
Ускорьте документ сериализации, подтверждающий, что способ сериализации/десериализации элементов использует двоичный/текстовый архив с потоком в базовой структуре. Это отлично работает, если я не буду использовать сериализованные данные как std::string, но я намерен преобразовать его непосредственно в буфер char *. Как я могу достичь этого, не создавая временную строку?
Решено! Для тех, кому нужен пример:
char buffer[4096];
boost::iostreams::basic_array_sink<char> sr(buffer, buffer_size);
boost::iostreams::stream< boost::iostreams::basic_array_sink<char> > source(sr);
boost::archive::binary_oarchive oa(source);
oa << serializable_object;
IIUC, вы хотите записать в предварительно выделенный массив фиксированного размера.
Вы можете использовать boost:: iostreams:: array_sink (завернутый stream, чтобы предоставить ему интерфейс std:: ostream).
Если вы не знаете размер данных, которые вы отправляете заранее, это общий способ сериализации в std::string
:
// serialize obj into an std::string
std::string serial_str;
boost::iostreams::back_insert_device<std::string> inserter(serial_str);
boost::iostreams::stream<boost::iostreams::back_insert_device<std::string> > s(inserter);
boost::archive::binary_oarchive oa(s);
oa << obj;
// don't forget to flush the stream to finish writing into the buffer
s.flush();
// now you get to const char* with serial_str.data() or serial_str.c_str()
Для десериализации используйте
// wrap buffer inside a stream and deserialize serial_str into obj
boost::iostreams::basic_array_source<char> device(serial_str.data(), serial_str.size());
boost::iostreams::stream<boost::iostreams::basic_array_source<char> > s(device);
boost::archive::binary_iarchive ia(s);
ia >> obj;
Это работает как шарм, я использую его для отправки данных с помощью MPI.
Это можно сделать очень быстро, если вы сохраните serial_str
в памяти и просто вызовите serial_str.clear()
, прежде чем сериализовать его. Это очищает данные, но не освобождает память, поэтому никакого распределения не произойдет, когда ваш следующий размер данных сериализации не потребует этого.
std::stringstream
:// access data with .data() and size with .size()
using RawDataBuffer = std::string;
RawDataBuffer serialize(const Foo &obj) {
std::stringstream ss;
boost::archive::binary_oarchive oa(ss);
oa << obj;
return ss.str();
}
Foo deserialize(const RawDataBuffer &data) {
std::stringstream ss(data);
boost::archive::binary_iarchive ia(ss);
Foo obj; // Foo must be default-constructible
ia >> obj;
return obj;
}
Полный рабочий пример, скомпилированный с boost 1.66:
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <sstream>
#include <iostream>
class Foo {
public:
Foo() = default;
Foo(int i) : _i(i)
{}
int get() const
{ return _i; }
protected:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /* version */ )
{
ar & _i;
}
private:
int _i;
};
// access data with .data() and size with .size()
using RawDataBuffer = std::string;
RawDataBuffer serialize(const Foo &obj) {
std::stringstream ss;
boost::archive::binary_oarchive oa(ss);
oa << obj;
return ss.str();
}
Foo deserialize(const RawDataBuffer &data) {
std::stringstream ss(data);
boost::archive::binary_iarchive ia(ss);
Foo obj; // Foo must be default-constructible
ia >> obj;
return obj;
}
int main()
{
RawDataBuffer buff;
{
Foo fortyTwo(42);
buff = serialize(fortyTwo);
}
{
Foo reborn;
reborn = deserialize(buff);
std::cout << "Reborn from " << reborn.get() << std::endl;
}
}