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
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?
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
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
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 << ", ";
}
}
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);
}