Deserialize multiple values with boost::serialize (with SSCCE) - c++

I try to serialize and deserialize an object with boost::serialize library. I need to split my save and load function.
I use the library is described in the official tutorial. My save and load functions look like this:
friend class boost::serialization::access;
template<typename Archive>
void save(Archive& ar, const unsigned version) const {
ar & name;
ar & NType;
ar & NTherm;
ar & NRun;
//...
}
template<class Archive>
void load(Archive& ar, const unsigned int version) {
ar & name;
ar & NType;
ar & NTherm;
ar & NRun;
//...
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
These functions are implemented in the header of a class. I serialize and deserialize like this:
{
//Serialize
std::ofstream ofs("output.txt");
boost::archive::text_oarchive oa(ofs);
oa << Object;
}
{
//Deserialize
Class newObject;
std::ifstream ifs("output.txt");
boost::archive::text_iarchive ia(ifs);
ia >> newObject;
}
Serialization works fine but while deserialization throws an exception at ar & NRun;.
An error message pops up which says: This application has requested the Runtime to terminate it in an unusual way. Debugging showed that an exception class name too long was thrown.
How can I fix this?
Update: Added brackets in the code snippet.
Update2: I added an SSCCE.
main.cpp:
#include <iostream>
#include "simulation.h"
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/split_member.hpp>
int main()
{
Simulation *sim;
sim = new Simulation(2,25,25,25,100,500,1000,"Sim");
{
std::ofstream ofs("output.txt");
boost::archive::text_oarchive oa(ofs);
oa << sim;
}
{
Simulation newSim;
std::ifstream ifs("output.txt",std::ios::binary);
boost::archive::text_iarchive ia(ifs);
ia >> newSim;
}
}
simulation.h:
#ifndef SIMULATION_H_
#define SIMULATION_H_
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/string.hpp>
class Simulation {
public:
//Constructors
Simulation(int anzType, int x=25, int y=25, int z=25, int NT = 100, int NS = 500, int NR = 1000, std::string n = "");
Simulation(); //Defaultconstructor für Boost Serialisierung
//Destructor
virtual ~Simulation();
private:
int NType;
int NTherm;
int NStep;
int NRun;
std::string name;
int Lx;
int Ly;
int Lz;
int LyLz;
friend class boost::serialization::access;
template<typename Archive>
void save(Archive& ar, const unsigned version) const {
ar & name;
ar & NType;
ar & NTherm;
ar & NRun;
ar & NStep;
}
template<class Archive>
void load(Archive& ar, const unsigned int version) {
ar & name;
ar & NType;
ar & NTherm;
ar & NRun;
ar & NStep;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
};
#endif /* SIMULATION_H_ */
simulation.cpp:
#include "Simulation.h"
Simulation::Simulation() {
}
Simulation::Simulation(int anzType, int x, int y, int z, int NT, int NS, int NR, std::string n) {
name = n;
NType = anzType;
NTherm = NT;
NStep = NS;
NRun = NR;
Lx = x;
Ly = y;
Lz = z;
LyLz = y*z;
}
Simulation::~Simulation() {
}

UPDATE Since you updated the question with a SSCCE, it's obvious.
You serialize a Simulation*. And then you try to deserialize a Simulation&. Unsurprisingly, this won't work.
Live On Coliru
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <fstream>
#include <iostream>
class Simulation {
public:
// Constructors
Simulation(int anzType, int x = 25, int y = 25, int z = 25, int NT = 100, int NS = 500, int NR = 1000, std::string n = "");
Simulation(); // Defaultconstructor für Boost Serialisierung
// Destructor
virtual ~Simulation();
private:
std::string name;
int NType, NTherm, NStep, NRun;
int Lx, Ly, Lz, LyLz;
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive &ar, unsigned) {
ar & name;
ar & NType;
ar & NTherm;
ar & NRun;
ar & NStep;
}
};
Simulation::Simulation() {}
Simulation::Simulation(int anzType, int x, int y, int z, int NT, int NS, int NR, std::string n)
: name(n), NType(anzType), NTherm(NT), NStep(NS), NRun(NR),
Lx(x), Ly(y), Lz(z), LyLz(y * z)
{
}
Simulation::~Simulation() {}
int main() {
Simulation *sim = new Simulation(2, 25, 25, 25, 100, 500, 1000, "Sim");
{
std::ofstream ofs("output.txt", std::ios::binary);
boost::archive::text_oarchive oa(ofs);
oa << sim;
}
{
Simulation* newSim = nullptr;
std::ifstream ifs("output.txt", std::ios::binary);
boost::archive::text_iarchive ia(ifs);
ia >> newSim;
delete newSim;
}
}

Related

C++ Boot serialization cause a segmentation fault

I have those two classes and I'm trying to deserialize them using boost
class WorldItem
{
private:
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar &foreground;
ar &background;
ar &breakLevel;
ar &breakTime;
ar &water;
ar &fire;
ar &glue;
ar &red;
ar &green;
ar &blue;
}
public:
int foreground = 0;
int background = 0;
int breakLevel = 0;
long long int breakTime = 0;
bool water = false;
bool fire = false;
bool glue = false;
bool red = false;
bool green = false;
bool blue = false;
};
class Worlds
{
private:
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar &width;
ar &height;
ar &name;
for (int i = 0; i < 100 * 60; i++)
{
ar &items[i];
}
ar &owner;
ar &weather;
ar &isPublic;
ar &isNuked;
}
public:
int width;
int height;
string name;
WorldItem *items;
string owner = "";
int weather = 0;
bool isPublic = false;
bool isNuked = false;
};
Here I'm creating a world in this way
Worlds generateWorld(string name, int width, int height)
{
Worlds world;
world.name = name;
world.width = width;
world.height = height;
world.items = new WorldItem[100 * 60];
}
and here im using this function to serialize the world
std::stringstream serialize_world(Worlds world)
{
std::stringstream str;
{
boost::archive::binary_oarchive oa(str);
oa << world;
}
return str;
}
So the serialize_world function is working without issues and i am inserting it value to mysql longblob.
But now when I'm trying to get the blob from MySql and deserialize it back by using this function
Worlds deserialize(std::string world)
{
Worlds wld;
std::istream *blobdata = WORLD_DATA(world);
{
boost::archive::binary_iarchive ia(*blobdata);
ia >> wld;
}
return wld;
}
I'm getting a Segmentation fault (core dumped) I don't know what's wrong.
Thanks.
Looks like you never return a value from generateWorld.
My compiler warns about this. Try enabling your compiler's diagnostics. I usually have -Wall -Wextra -pedantic enabled
Also in deserialize you never initialize items to anything. That is going to lead to UB.
This, too, could be diagnosed by most compilers (-fsanitize=address,undefined helps, although it makes compilation and runtime slow). There's also external tools like Valgrind that do these
Finally, I have no idea what is going on with blobdata, so I'm going to ignore that, but it too looks wrong.
Don't use raw new/delete
See also e.g. https://www.quora.com/Why-are-the-%E2%80%98new%E2%80%99-and-%E2%80%98delete%E2%80%99-keywords-considered-bad-in-modern-C++
Just use std::array then and be happy:
Live On Coliru
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/array.hpp>
#include <array>
#include <iostream>
#include <sstream>
class WorldItem {
private:
friend class boost::serialization::access;
template <class Ar> void serialize(Ar& ar, unsigned) {
ar& foreground& background& breakLevel& breakTime& water& fire& glue&
red& green& blue;
}
public:
int foreground = 0;
int background = 0;
int breakLevel = 0;
long long int breakTime = 0;
bool water = false;
bool fire = false;
bool glue = false;
bool red = false;
bool green = false;
bool blue = false;
auto operator<=>(WorldItem const&) const = default;
};
class Worlds
{
private:
friend class boost::serialization::access;
template <class Ar> void serialize(Ar& ar, unsigned) {
ar& width& height& name& items& owner& weather& isPublic& isNuked;
}
public:
int width;
int height;
std::string name;
std::array<WorldItem, 100 * 60> items;
std::string owner = "";
int weather = 0;
bool isPublic = false;
bool isNuked = false;
auto operator<=>(Worlds const&) const = default;
};
//So here im creating a world in this way
Worlds generateWorld(std::string name, int width, int height) {
Worlds world;
world.name = name;
world.width = width;
world.height = height;
return world;
}
std::string serialize_world(Worlds const& world) {
std::stringstream str;
{
boost::archive::binary_oarchive oa(str);
oa << world;
}
return str.str();
}
Worlds deserialize(std::string world) {
Worlds wld;
std::istringstream blobdata(world);
{
boost::archive::binary_iarchive ia(blobdata);
ia >> wld;
}
return wld;
}
int main() {
Worlds w = generateWorld("test", 6, 6);
Worlds clone = deserialize(serialize_world(w));
std::cout << "Worlds equal? " << std::boolalpha << (w == clone) << "\n";
}
Prints
Worlds equal? true

Boost serializing - adding armadillo matrices that have namespaces to a class

I have successfully serialized armadillo without a class matrices here:
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <armadillo>
#include <boost/serialization/split_member.hpp>
BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive & ar, const arma::mat &t, unsigned int version)
{
ar & t.n_rows;
ar & t.n_cols;
const double *data = t.memptr();
for(int K=0; K<t.n_elem; ++K)
ar & data[K];
}
template<class Archive>
void load(Archive & ar, arma::mat &t, unsigned int version)
{
int rows, cols;
ar & rows;
ar & cols;
t.set_size(rows, cols);
double *data = t.memptr();
for(int K=0; K<t.n_elem; ++K)
ar & data[K];
}
}}
int main() {
arma::mat A = arma::randu<arma::mat>(4,5);
std::ofstream outputStream;
outputStream.open("bin.dat");
std::ostringstream oss;
boost::archive::binary_oarchive oa(outputStream);
oa & A;
outputStream.close();
arma::mat B;
std::ifstream inputStream;
inputStream.open("bin.dat", std::ifstream::in);
boost::archive::binary_iarchive ia(inputStream);
ia & B;
return 0;
}
But my end goal is to have arma matrices within a class, alongside typical data types (int, double, float, etc.) and be able to either serialize everything or specific data from the class. I also got it to work, that the normal data types could be serialized:
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <sstream>
#include <boost/serialization/split_member.hpp>
class Gear {
public:
template<typename Archive>
void serialize(Archive& ar, unsigned int version) { ar & v; }
void setV (const double& _v) { v = _v; }
double getV () { return v; }
void status () { std::cout << "v = " << v << std::endl; }
private:
double v;
};
class Car {
public:
template<typename Archive>
void serialize(Archive& ar, unsigned int version) {
ar & hp;
ar & x;
}
void setHP (const int& _hp) { hp = _hp; }
void setGear (Gear* _Gear) { x = _Gear; }
void status () { std::cout << "hp = " << hp << " Gear with v = " << x->getV() << std::endl; }
private:
int hp;
Gear *x;
};
int main() {
// Define new Gear:
Gear* g = new Gear();
g->setV(2.5);
g->status();
// Expectation is Car sets up the Gear.
Car c;
c.setHP(80);
c.setGear(g);
//c.status();
std::ofstream outputStream;
outputStream.open("bin.dat");
std::ostringstream oss;
boost::archive::binary_oarchive oa(outputStream);
oa & c;
outputStream.close();
Car b;
std::ifstream inputStream;
inputStream.open("bin.dat", std::ifstream::in);
boost::archive::binary_iarchive ia(inputStream);
ia & b;
b.status();
return 0;
}
So that works perfect, but I want to include the arma code (essentially) into the class. I tried to put the arma code within the class like such:
class Car {
public:
template<typename Archive>
void serialize(Archive& ar, unsigned int version) {
ar & hp;
ar & x;
}
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive & ar, const arma::mat &t, unsigned int version)
{
ar & t.n_rows;
ar & t.n_cols;
const double *data = t.memptr();
for(int K=0; K<t.n_elem; ++K)
ar & data[K];
}
template<class Archive>
void load(Archive & ar, arma::mat &t, unsigned int version)
{
int rows, cols;
ar & rows;
ar & cols;
t.set_size(rows, cols);
double *data = t.memptr();
for(int K=0; K<t.n_elem; ++K)
ar & data[K];
}
} }
arma::mat A;// = arma::randu<arma::mat>(4,5);
void setHP (const int& _hp) { hp = _hp; }
void setGear (Gear* _Gear) { x = _Gear; }
void status () { std::cout << "hp = " << hp << " Gear with v = " << x->getV() << A<< std::endl; }
private:
int hp;
Gear *x;
};
And then in the int main():
Car c;
c.setHP(80);
c.setGear(g);
c.A = arma::randu<arma::mat>(4,5);
After trying to compile the attempt, I am getting the errors:
g++ -std=c++11 arma_serial_binary_versuch.cpp -larmadillo -lboost_serialization
arma_serial_binary_versuch.cpp:52:3: error: expected unqualified-id before ‘namespace’
namespace boost {
^
arma_serial_binary_versuch.cpp:121:1: error: expected ‘}’ at end of input
}
^
arma_serial_binary_versuch.cpp: In member function ‘void Car::serialize(Archive&, unsigned int)’:
arma_serial_binary_versuch.cpp:48:12: error: ‘hp’ was not declared in this scope
ar & hp;
^
arma_serial_binary_versuch.cpp:49:12: error: ‘x’ was not declared in this scope
ar & x;
^
arma_serial_binary_versuch.cpp: At global scope:
arma_serial_binary_versuch.cpp:50:5: error: expected unqualified-id at end of input
}
I've read that it's not possible to work with namespaces within a class but I am unsure of a workaround this. Anyone have any ideas/recommendations?

Boost binary serialization - double array of fixed length error

I'm creating a class that stores lots of doubles for saving/loading with boost. The load needs to be as fast as possible, so getting the binary format to work is the goal.
Basically, I have a class that stores a vector of structs:
vector<DataChunk>
where DataChunk stores a double array of fixed length
double data[2048]
When I test the functionality with using a text archive (text_iarchive), everything works great. However, when using the binary archive, I get memory access violation on deserializing the class.
More bizarrely, if I fill the double array with the same double value (i.e all elements of data[2048] are equal to 12345), it works. Varying double values seems to crash it, though (see below).
Here's my RawData class:
#pragma once
#include <boost\serialization\vector.hpp>
#include <boost\serialization\array.hpp>
using namespace std;
struct DataChunk
{
public:
double data[2048]; //THIS IS THE PROBLEM AREA
int end;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & data;
ar & end;
}
};
class RawData
{
private:
vector<DataChunk> chunks;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & chunks;
}
public:
void add_chunk(DataChunk chunk){chunks.push_back(chunk);};
vector<DataChunk> get_chunks(){return chunks;};
static void save(RawData rd, string path);
static bool load(RawData & rd, string path);
void add_raw_data(vector<double> raw_data);
vector<double> combine_chunks();
};
My save and load functions look like this:
void RawData::save(RawData rd, string path)
{
std::ofstream file(path);
if(file.good())
{
boost::archive::binary_oarchive oa(file, std::ios::binary);
//boost::archive::text_oarchive oa(file);
oa << rd;
}
file.flush();
file.close();
}
bool RawData::load(RawData & rd, string path)
{
std::ifstream file(path);
if(file.good())
{
boost::archive::binary_iarchive ia(file, std::ios::binary);
//boost::archive::text_iarchive ia(file);
ia >> rd;
file.close();
return true;
}
else
return false;
}
In my main function, I test it like this:
string path = "test.data";
RawData old_data;
vector<double> raw_data;
for(int i = 0; i < 5000; i++)
raw_data.push_back(i * 2048); //change this to constant value and it works...
old_data.add_raw_data(raw_data);
//serialize
RawData::save(old_data, path);
//deserialize
RawData new_data;
RawData::load(new_data, path);
//grab the chunks and test the values
vector<DataChunk> chunks_in = new_data.get_chunks();
for(int i = 0; i < chunks_in.size(); i++)
for(int j = 0; j < chunks_in[i].end; j++)
cout<<chunks_in[i].data[j]<<", ";
return 0;
You will want to use
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & end;
ar & boost::serialization::make_array(data, end);
}
See http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/wrappers.html#arrays
Here is the demo, selfcontained:
Live On Coliru
#include <boost/serialization/vector.hpp>
#include <boost/serialization/array.hpp>
struct DataChunk {
public:
double data[2048]; // THIS IS THE PROBLEM AREA
int end;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & end;
ar & boost::serialization::make_array(data, end);
}
};
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
class RawData {
private:
std::vector<DataChunk> chunks;
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) { ar &chunks; }
public:
void add_chunk(DataChunk chunk) { chunks.push_back(chunk); };
std::vector<DataChunk> get_chunks() { return chunks; };
static void save(RawData rd, std::string path);
static bool load(RawData &rd, std::string path);
void add_raw_data(std::vector<double> raw_data) {
DataChunk chunk;
auto const csize = boost::size(chunk.data);
size_t n = raw_data.size(),
offs = 0ul;
while (n>0) {
auto n_ = std::min(n, csize);
std::copy_n(raw_data.begin() + offs, n_, chunk.data);
chunk.end = n_;
chunks.push_back(chunk);
offs += n_;
n -= n_;
}
}
std::vector<double> combine_chunks() {
std::vector<double> r;
boost::for_each(chunks, [&r](DataChunk const& c) {std::copy_n(c.data, c.end, back_inserter(r));});
return r;
}
};
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <fstream>
void RawData::save(RawData rd, std::string path) {
std::ofstream file(path);
if (file.good()) {
boost::archive::binary_oarchive oa(file, std::ios::binary);
// boost::archive::text_oarchive oa(file);
oa << rd;
}
file.flush();
file.close();
}
bool RawData::load(RawData &rd, std::string path) {
std::ifstream file(path);
if (file.good()) {
boost::archive::binary_iarchive ia(file, std::ios::binary);
// boost::archive::text_iarchive ia(file);
ia >> rd;
file.close();
return true;
} else
return false;
}
#include <iostream>
RawData generate() {
RawData data;
std::vector<double> raw_data;
for (int i = 0; i < 5000; i++)
raw_data.push_back(i * 2048);
data.add_raw_data(raw_data);
return data;
}
int main() {
std::string const path = "test.data";
{
// serialize
RawData const old_data = generate();
RawData::save(old_data, path);
}
{
// deserialize
RawData new_data;
RawData::load(new_data, path);
// grab the chunks and test the values
for (auto d : new_data.combine_chunks())
std::cout << d << ", ";
}
}

Maximum Size that a Boost Message Queue can Handle?

What is the maximum size a Boost Message Queue can Handle?
When I am sending and receiving the below structure by using Boost binary serialization it is working fine.
typedef struct {
int msg_type;
char msg_name[100];
union {
struct {
int ID;
std::string ReportedTime;
char ReceivedAt[200];
int Number;
int Priority;
} mess1;
struct {
char host_ip[20];
char mac_addr[30];
char time_stamp[100];
} mess2;
} struct_type;
}msg_struct;
#include <boost/serialization/is_bitwise_serializable.hpp>
BOOST_IS_BITWISE_SERIALIZABLE(msg_struct)
But when I making the size of ReceivedAt[2000] to 2000 or adding a new char array variable.
It is throwing the following exception and the core is getting dumped.
terminate called after throwing an instance of 'boost::interprocess::interprocess_exception'
what(): boost::interprocess_exception::library_error
Aborted (core dumped)
Edit
Send
int ControlQueue::pushMessage(msg_struct* msg)
{
int q_size = vamsgq->get_num_msg();
int retVal = 0;
lockQueue();
//imp->ID=1;
//strcpy(imp->ReceivedAt,"10-07-14");
std::stringstream oss;
boost::archive::binary_oarchive oa(oss);
strncpy(msg->msg_name,"msg_name",sizeof(msg->msg_name));
oa << boost::serialization::make_array(msg, 1);
std::string serialized_string(oss.str());
vamsgq->send(serialized_string.data(), serialized_string.size(), 0);
std::cout <<"\n sendig type="<< msg->msg_name << std::endl;
if((retVal = pthread_cond_signal(&m_qCondSignal)) != 0)
{
cout<<__FILE__<<__LINE__<<
"{ControlQueue %x} Unable to send Cond Signal",this);
}
unlockQueue();
return 1;
}
Recieve:
msg_struct* ControlQueue::getMsg()
{
int retVal = 0;
message_queue::size_type recvd_size;
unsigned int priority;
lockQueue();
while(vamsgq->get_num_msg()==0)
{
if((retVal = pthread_cond_wait(&m_qCondSignal, &m_qMutex)) != 0)
{
cout<<__FILE__<<__LINE__<<"getMsg {ControlQueue } Unable to Cond Signal";
unlockQueue();
return NULL;
}
}
msg_struct *l_msg_struct = NULL;
if(vamsgq->get_num_msg())
{
l_msg_struct=new msg_struct();
std::stringstream iss;
std::string serialized_string;
serialized_string.resize(MAX_SIZE);
vamsgq->receive(&serialized_string[0], MAX_SIZE, recvd_size, priority);
iss << serialized_string;
boost::archive::binary_iarchive ia(iss);
ia >> boost::serialization::make_array(l_msg_struct, 1);
std::cout <<"Recieving="<< l_msg_struct->msg_name << std::endl;
}
else
{
cout<<__FILE__<<__LINE__<<"getMsg {ControlQueue } m_MsgQ empty..";
}
unlockQueue();
return l_msg_struct;
}
The Send and Receive both are running in different threads the only problem what I am getting is after increasing the size of structure or adding an char array variable.
And the exception is getting thrown by the vamsgq->send() method, Creation method(message queue) is working fine. And I am also increasing the size of Message that message queue is going to store.
Is there any complete documentation online for the boost::message_queue.
You broke the requirement for
BOOST_IS_BITWISE_SERIALIZABLE(msg_struct)
by no longer keeping the msg_struct a POD type:
static_assert(boost::is_pod<msg_struct>::value, "msg_struct must be POD");
will fail to compile. (In fact, with the msg_struct shown using std::string, I think default construction should fail to compile, so the new msg_struct() line in your example confuses me).
Also you don't show the construction of the message-queue, so I can't tell how you determine the maximum message size. This might be inadequately dimensioned. See below for two approaches that use/check the size limitations.
Here's what would work:
[Solution A] All POD data, no serialization
#include <boost/serialization/serialization.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
typedef struct {
int msg_type;
char msg_name[100];
union {
struct {
int ID;
char ReportedTime[100];
char ReceivedAt[2000];
int Number;
int Priority;
} mess1;
struct {
char host_ip[20];
char mac_addr[30];
char time_stamp[100];
} mess2;
} struct_type;
} msg_struct;
static_assert(boost::is_pod<msg_struct>::value, "msg_struct must be POD");
#include <boost/serialization/is_bitwise_serializable.hpp>
BOOST_IS_BITWISE_SERIALIZABLE(msg_struct)
namespace ipc = boost::interprocess;
int main() {
ipc::message_queue queue(ipc::open_or_create, "myqueue", 100, sizeof(msg_struct));
msg_struct outgoing;
outgoing.msg_type = 1;
strncpy(outgoing.msg_name, "outgoing.msg_name", sizeof(outgoing.msg_name));
outgoing.struct_type.mess1.ID = 42;
strncpy(outgoing.struct_type.mess1.ReportedTime, "outgoing.struct_type.mess1.ReportedTime", sizeof(outgoing.struct_type.mess1.ReportedTime));
strncpy(outgoing.struct_type.mess1.ReceivedAt, "outgoing.struct_type.mess1.ReceivedAt", sizeof(outgoing.struct_type.mess1.ReceivedAt));
outgoing.struct_type.mess1.Number = 123;
outgoing.struct_type.mess1.Priority = 234;
queue.send(&outgoing, sizeof(outgoing), 1);
}
As you can see, this is not using Boost Serialization because the struct is POD anyways.
[Solution B] Highlevel C++ types, using binary serialization
Alternatively, you can use Boost Serialization all the way and check that the message size doesn't exceed the maximum message size when sending:
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
typedef struct {
int msg_type;
std::string msg_name;
struct mess1_t {
int ID;
std::string ReportedTime;
std::string ReceivedAt;
int Number;
int Priority;
private:
friend class boost::serialization::access;
template <typename Ar>
void serialize(Ar& ar, unsigned)
{
ar & ID;
ar & ReportedTime;
ar & ReceivedAt;
ar & Number;
ar & Priority;
}
};
struct mess2_t {
std::string host_ip;
std::string mac_addr;
std::string time_stamp;
private:
friend class boost::serialization::access;
template <typename Ar>
void serialize(Ar& ar, unsigned)
{
ar & host_ip;
ar & mac_addr;
ar & time_stamp;
}
};
boost::variant<mess1_t, mess2_t> message_data;
private:
friend class boost::serialization::access;
template <typename Ar>
void serialize(Ar& ar, unsigned)
{
ar & msg_type;
ar & msg_name;
ar & message_data;
}
} msg_struct;
namespace ipc = boost::interprocess;
int main() {
ipc::message_queue queue(ipc::open_or_create, "myqueue", 100, 4*1024);
msg_struct outgoing { 1, "outgoing.msg_name", msg_struct::mess1_t {
42,
"outgoing.struct_type.mess1.ReportedTime",
"outgoing.struct_type.mess1.ReceivedAt",
123,
234 }
};
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);
oa << outgoing;
assert(oss.str().size() <= queue.get_max_msg_size());
queue.send(&outgoing, sizeof(outgoing), 1);
}

C++ Boost deserialization what(): input stream error

I'm trying to make a serialization of an object and then to deserialize it. Even though it seems that everything I wrote is ok I'm still getting an error during the deserialization.
int main(){
MapAttributes mapAtt(MAP_SIZE,MAP_SIZE);
initMapFromImage("map1.png",&mapAtt);
int prevxMax = mapAtt.prevxMax ;
int prevyMax = mapAtt.prevyMax ;
int prevxMin = mapAtt.prevxMin ;
int prevyMin = mapAtt.prevyMin ;
PixelCoords pose = PixelCoords(mapAtt.robotPose.dx, mapAtt.robotPose.dy);
PixelCoords target = PixelCoords( 2048+250, 2048+250 );
PartitionGraphNodes partitionGraph(&mapAtt);
PartitionGraphNodes partitionGraph2(&mapAtt);
partitionGraph.createIncrementalPartition(pose,target);
if (partitionGraph.nodes.size()!=0){
saveSerializedObject<PartitionGraphNodes(partitionGraph,"partition_graph_marshall");
std::cout << "size= " << partitionGraph.nodes.size() << "\n";
restoreSerializedObject<PartitionGraphNodes>(partitionGraph2,"partition_graph_marshall");
}
else{
std::cout << "RUN FOR YOUR LIVES!!!\n";
}
return 0;
This is my code where I'm trying to get my objects serialized and deserialized.
Here is the function for the serialization and the deserialization:
template<class T>
void saveSerializedObject(const T &s, const char * filename){
// make an archive
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << s;
}
template<class T>
void restoreSerializedObject(T &s, const char * filename)
{
// open the archive
std::ifstream ifs(filename);
if (ifs.good()) {
std::cout << "Coming!!!\n";
boost::archive::text_iarchive ia(ifs);
ia >> s;
} else {
// throw an error or something
assert(false);
}
}
Finally I have wrote the code for the serialization exactly as the Boost documentation suggests, but I still get an error: an instance of 'boost::archive::archive_exception' what(): input stream error. Can you help me with that?
EDIT:
As it is clear enough, initially I'm trying to serialize an object of class PartitionGraphNodes. So this is how an PartitionGraphNodes object is serialized:
#include <boost/serialization/base_object.hpp>
class PartitionGraphNodes: public NodesVector{
private:
std::vector<int> targetNeighbors; //!<Vector holding target neighbors
std::vector<int> robotNeighbors; //!<Vector holding robot neighbors
std::vector<PixelCoords> uniformPartition;
public:
PartitionGraphNodes(MapAttributes* mapAttr);
void createIncrementalPartition(PixelCoords startPos, PixelCoords target);
int insertNodeInPartition(Node currNode);
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// serialize base class information
std::cout << "In partition_serial" << "\n";
ar & boost::serialization::base_object<NodesVector>(*this);
}
};
#include <boost/serialization/vector.hpp>
class NodesVector{
protected:
//~ std::vector<Voronode> nodes;
public:
NodesVector(void){};
std::vector<Node> nodes;
MapAttributes* mapAttributes;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
std::cout << "In nodesVector_serial" << "\n";
ar & nodes;
}
};
#include <boost/serialization/vector.hpp>
class Node{
public:
PixelCoords p; //!< The coordinates of the node
bool visited; //!< True if the node has been visited
unsigned int ID; //!< The node's ID
int parent;
std::vector<PixelCoords> neigh; //!< Vector of the neighbors of the node (coords)
std::vector<unsigned int> neighID; //!< Vector of the neighbors' IDs
std::vector<float> dist; //!< Vector of the distances of the neighbors
Weight w; //!< The node's weight
std::vector<PixelCoords> path;
Node(PixelCoords a) {p=a;}
Node(PixelCoords a,unsigned int IDt) {p=a; ID=IDt;}
Node(void){}
void makeNeighbor(Node &a);
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
std::cout << "In nodes_serial" << "\n";
ar & p;
ar & visited;
ar & ID;
ar & parent;
ar & neigh;
ar & neighID;
ar & dist;
ar & w;
}
};
#endif
I think you need
BOOST_CLASS_EXPORT();
lines.
See for instance the answers to this question: Where to put BOOST_CLASS_EXPORT for boost::serialization?