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

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?

Related

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?

C++ Boost - serialization of class containing class-hierarchy objects

I have a class A, which contains the object of class B and I want to serialize it. The problem is, the class C inherits from B, so A can contain an object of either B or C. How can I efficiently implement the serialization with Boost?
My attempt is below, but I'm getting the error when trying to serialize A with C object, while with B it works correctly. Do you know, what am I doing wrong?
I've found some information about class-hierarchy objects serialization here, but it requires an explicit registration of the type in text_iarchive, whereas I need it to be registered in the A class because I'm not directly serializing B objects.
My attempt:
#include <fstream>
#include <iostream>
#include <vector>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
class B {
friend class boost::serialization::access;
private:
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
ar & this->v->size();
for(int i = 0; i < this->v->size(); i++) {
ar & (*(this->v))[i];
}
};
template<class Archive>
void load(Archive & ar, const unsigned int version) {
size_t size;
int tmp;
ar & size;
this->v = new std::vector<int>(size);
for(int i = 0; i < size; i++) {
ar & tmp;
(*this->v)[i] = tmp;
}
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
protected:
std::vector<int>* v;
public:
B();
B(std::vector<int>* v);
virtual void print_vals();
};
B::B() {
this->v = nullptr;
}
B::B(std::vector<int>* v) {
this->v = v;
}
void B::print_vals() {
for(auto e : *(this->v)) {
std::cout << e << std::endl;
}
}
class C : public B {
friend class boost::serialization::access;
private:
int num2;
template<class Archive>
void serialize(Archive & ar, const unsigned int version){
ar & boost::serialization::base_object<B>(*this);
ar & num2;
};
public:
void print_vals() override {
for(auto e : *(this->v)) {
std::cout << e << std::endl;
}
std::cout << this->num2 << std::endl;
}
C();
C(int num2, std::vector<int>* v);
};
C::C() {
this->num2 = -1;
this->v = nullptr;
}
C::C(int num2, std::vector<int> *v) {
this->num2 = num2;
this->v = v;
}
class A {
friend class boost::serialization::access;
private:
int num;
B* b_obj;
template<class Archive>
void serialize(Archive & ar, const unsigned int version){
ar & num;
ar & b_obj;
};
public:
A();
A(int num, B* b);
void print_vals();
};
A::A() {
this->num = -1;
this->b_obj = nullptr;
}
A::A(int num, B* b) {
this->num = num;
this->b_obj = b;
}
void A::print_vals() {
std::cout << this->num << std::endl;
this->b_obj->print_vals();
}
int main() {
std::vector<int> v{1,2,3};
B b = B(&v);
A a(4, &b);
std::cout << "a:" << std::endl;
a.print_vals();
std::ofstream ofs("a.txt");
{
boost::archive::text_oarchive oa(ofs);
oa << a;
ofs.close();
}
A a2;
std::ifstream ifs("a.txt");
{
boost::archive::text_iarchive ia(ifs);
ia >> a2;
ifs.close();
}
std::cout << "a2:" << std::endl;
a2.print_vals();
C c(2, &v);
A a3(6, &c);
std::cout << "a3:" << std::endl;
a3.print_vals();
std::ofstream ofs2("a3.txt");
{
boost::archive::text_oarchive oa(ofs2);
oa << a3;
ofs.close();
}
A a4;
std::ifstream ifs2("a3.txt");
{
boost::archive::text_iarchive ia(ifs2);
ia >> a4;
ifs.close();
}
std::cout << "a4:" << std::endl;
a4.print_vals();
}
OUTPUT:
a:
4
1
2
3
a2:
4
1
2
3
a3:
6
1
2
3
2
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): unregistered class - derived class not registered or exported
Signal: SIGABRT (Aborted)
It turns that you have missed BOOST_CLASS_EXPORTfor derived class, i.e.
BOOST_CLASS_EXPORT(C)
Boost serialization cannot serialize pointer to derived object correctly without this macro.
You can find full working code here

Serializing struct containing vector of pointers with each pointer containing other pointers

I'm trying to serialize a minHeap object which contains a vector and an integer using Boost.
struct minHeap {
std::vector<keyNode> heapStructure; // A vector of many keyNodes
int size; // Current size of vector
minHeap() {
size = 0;
}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned version)
{
ar & heapStructure;
ar & size;
}
};
Now the heapStructure is a vector of keyNode and each keyNode contains a character, integer and two pointers of the object keyNode itself.
struct keyNode {
char data; // The character itself
int frequency; // Occurances of the character in the data stream.
keyNode * leftNode, *rightNode; // Left and right children of the root node (the keyNode itself)
keyNode() {
data = NULL;
frequency = 0;
leftNode = NULL;
rightNode = NULL;
}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned version)
{
ar &data;
ar &frequency;
ar &leftNode;
ar &rightNode;
}
};
The below (sample) code shows how I'm serializing and deserializing the file.
// Write Encoded Stream to File
ofstream outFile;
string outPath = filePath + ".enc";
outFile.open(outPath, ios::out | ios::binary); // TODO: Fix the output path
bitsetR bitStorage(outputStream);
boost::archive::binary_oarchive output(outFile);
output << bitStorage;
output << hTree;
outFile.close();
ifstream inFile;
inFile.open("demo.txt.enc"); // TODO: Fix the output path
bitsetR bitStr("");
boost::archive::binary_iarchive input(inFile);
minHeap temp;
input >> bitStr;
input >> temp;
I don't get any errors while serializing but deserializing fails with the following error (VS 2017):
Exception Thrown: Input Stream Error (boost::archive::archive_exception)
I should note here that the bitsetR object deserializes successfully. The exception is thrown when deserializing the minHeap object.
I think all that's needed is proper flush and close of the archive and stream in the correct order. This code works ok:
Live On Coliru
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/vector.hpp>
struct keyNode {
char data = 0; // The character itself
int frequency = 0; // Occurances of the character in the data stream.
keyNode *leftNode = nullptr;
keyNode *rightNode = nullptr; // Left and right children of the root node (the keyNode itself)
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar &data;
ar &frequency;
ar &leftNode;
ar &rightNode;
}
};
struct minHeap {
std::vector<keyNode> heapStructure; // A vector of many keyNodes
size_t size() const { return heapStructure.size(); }
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar &heapStructure;
}
};
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <fstream>
int main() {
minHeap hTree;
{
std::ofstream outFile("demo.txt.enc", std::ios::binary);
{
boost::archive::binary_oarchive output(outFile);
output << hTree;
}
}
{
std::ifstream inFile("demo.txt.enc");
boost::archive::binary_iarchive input(inFile);
minHeap temp;
input >> temp;
}
}
Note I can make it fail with a similar message by dropping the scopes:
int main() {
minHeap hTree;
std::ofstream outFile("demo.txt.enc", std::ios::binary);
boost::archive::binary_oarchive output(outFile);
output << hTree;
std::ifstream inFile("demo.txt.enc");
boost::archive::binary_iarchive input(inFile);
minHeap temp;
input >> temp;
}
Prints Live On Coliru
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): input stream error
bash: line 7: 16838 Aborted (core dumped) ./a.out

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);
}