boost polymorphic XML serialization problem
Problem.
While serializing a class through a polymorphic pointer you get:
terminate called after throwing an instance of 'boost::archive::archive_exception' what(): unregistered class
Its because you didn’t use the BOOST_CLASS_EXPORT(MyClass) macro.
or:
/usr/local/include/boost-1_35/boost/archive/detail/iserializer.hpp: 589: error: no matching function for call to ‘load_wrapper(boost::archive::xml_iarchive&, const float&, boost::serialization::is_wrapper)’
Its because you made the serialize function const (or the load function). Remove the const keyword and it will work. I got this error when I copied and passed the save function renaming it to load (they were to be almost identical, so why type the same again). And that was the trap, cos the shown error doesn’t give a clue what could be wrong. After some time I got it working, the load function changes the object so it cannot be const! Not a very fortunate mistype, I had to spend some time figuring out what is happening.
Use this sample, and adapt it to your case:
#include <fstream>
#include <iostream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/export.hpp>
class AbstractBase {
public:
virtual void base() = 0;
virtual ~AbstractBase() { }
};
BOOST_IS_ABSTRACT(AbstractBase)
class Derived1 : public AbstractBase {
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
boost::serialization::void_cast_register(
static_cast<Derived1 *>(NULL),
static_cast<AbstractBase *>(NULL)
);
ar & BOOST_SERIALIZATION_NVP(a1);
}
public:
float a1;
inline void base() { }
};
BOOST_CLASS_EXPORT(Derived1)
int main() {
AbstractBase* d1 = new Derived1();
std::ofstream ofs("filename.xml");
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(d1);
ofs.close();
return 0;
}
Very simple C++ boost xml serialization example
#include <fstream>
#include <iostream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
using namespace std;
class Test {
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(a);
ar & BOOST_SERIALIZATION_NVP(b);
ar & BOOST_SERIALIZATION_NVP(c);
}
int a;
int b;
float c;
public:
inline Test(int a, int b, float c) {
this->a = a;
this->b = b;
this->c = c;
}
};
int main() {
std::ofstream ofs("filename.xml");
Test* t = new Test(1, 2, 3.3);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(t);
return 0;
}
SSE with GCC and not aligned addresses
I am not familiar with the AT&T ASM programming and the GCC style of inline ASM. It took me some time to get it working. Here are the results. Some sample code that can add or multiply C/C++ float vectors using SSE instructions.
The vectors do not have to have 16-bit aligned addresses. That is why I needed this code. The provided along with GCC functions do not allow that. If you want to operate on an array and move the pointer by 1 unit, not by 4, than MOVUPS instead of MOVAPS necessary.
The code:
/**
* The input parameters 'a' and 'b' should be 4 element float vectors.
* The result should point to a 4 element float vector as well.
* The result is the SSL additon r=a+b.
*/
inline void addSSE(float* a, float* b, float* result) {
__asm__ __volatile__
(
"movups (%[a]), %%xmm0 \n\t"
"movups (%[b]), %%xmm1 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"movups %%xmm0, %[result] \n\t"
: [result] "=m" (*result)
: [a] "r" (a), [b] "r" (b)
: "%xmm0", "%xmm1"
);
}
/**
* The input parameters 'a' and 'b' should be 4 element float vectors.
* The result should point to a 4 element float vector as well.
* The result is the SSL multiplication r=a*b.
*/
inline void mulSSE(float* a, float* b, float* result) {
__asm__ __volatile__
(
"movups (%[a]), %%xmm0 \n\t"
"movups (%[b]), %%xmm1 \n\t"
"mulps %%xmm1, %%xmm0 \n\t"
"movups %%xmm0, %[result] \n\t"
: [result] "=m" (*result)
: [a] "r" (a), [b] "r" (b)
: "%xmm0", "%xmm1"
);
}