Sorry, I forgot to say:
In my code sample,
SERIALIZE_BASE = BOOST_SERIALIZATION_BASE_OBJECT_NVP
And SERIALIZE = BOOST_SERIALIZATION_NVP
(It's our custom define, in debug it's a little bit different to cout those
calls).
Thanks.
On Thu, Mar 14, 2019 at 6:49 PM Nicolas Guillot
Hello.
*** CONTEXT ***
I use your serialization library since several years on linux (gcc). Now, I'm moving to windows (_MSC_VER == 1600) (boost 1.55, but same issues on boost 1.69).
For my example, I use a class A in a DLL, another class B inheriting from A in its DLL and an exe, linked to those DLLs, which serializes a B object, through its A base.
_______ | A | ------- /_\ | | _______ | B | -------
I make a class serializable like that (I summurize on purpose (no #include, ...)). For A it's the same thing, but it has no base class.
----> B.h ---------------------------------------- #ifdef B_EXPORTS #define B_DLL __declspec(dllexport) #else #define B_DLL __declspec(dllimport) #endif
class B_DLL B: public A { public: B(); virtual ~B(); private: friend class boost::serialization::access; template <class Archive> void serialize(Archive & ar, const unsigned int version);
int i; }; BOOST_CLASS_EXPORT_KEY(B)
----> B.cpp ---------------------------------------- B::B() : i(123) {}
B::~B() {}
template <class Archive> void B::serialize(Archive & ar, const unsigned int) { ar & SERIALIZE_BASE(ClassA); ar & SERIALIZE(i); }
#define FULL_SCOPED_SERIALIZABLE_CLASS B #include "Common/InstanciateSerializationTemplate.h"
----> InstanciateSerializationTemplate.h ---------------------------------------- This file purpose is to instanciate the template B::serialize methods for each archive type, and to register the class. Here is its contents (once again, no namesapce nor include to make it easier to read):
// explicit instantiate code for all archive types expected to be use: // MUST COME BEFORE BOOST_CLASS_EXPORT_IMPLEMENT // binary: template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize
(binary_iarchive & ar, const unsigned int version); template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize (binary_oarchive & ar, const unsigned int version); // XML: template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize (xml_iarchive & ar, const unsigned int version); template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize (xml_oarchive & ar, const unsigned int version); // TXT: template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize (text_iarchive & ar, const unsigned int version); template __declspec(dllexport) void FULL_SCOPED_SERIALIZABLE_CLASS::serialize (text_oarchive & ar, const unsigned int version); BOOST_CLASS_EXPORT_IMPLEMENT(FULL_SCOPED_SERIALIZABLE_CLASS)
*** MY ISSUE ***
All that stuff works in linux, gcc, but not in Windows.
If I write in my exe this serialization code:
std::ofstream ofs; ofs.open("D:\\TestSerial.xml"); boost::archive::xml_oarchive ar(ofs);
shared_ptr<B> b = shared_ptr<B>(new B()); shared_ptr<A> a = b;
try { ar << SERIALIZE(a); } catch (boost::archive::archive_exception& ex) { std::cout << "Serialization to stream error, what: " << ex.what() << std::endl; } catch (...) { std::cout << "Catch ... Serialization to stream error" << std::endl; } ofs.close();
With this code, I have an archive_exception: "unregistered class - derived class not registered or exported".
I have to write the serialization like that:
ar.register_type(static_cast(0)); boost::serialization::void_cast_register(static_cast(0), static_cast(0)); ar << SERIALIZE(a);
*** QUESTION ***
At least, my question: I cannot do like that: what I would like to achieve: when a new class is made serializable like above, I expect the class to be registered automatically (probabley with BOOST_CLASS_EXPORT_IMPLEMENT in InstanciateSerializationTemplate.h). It's too painfull to write the register_type and void_cast_register each time I want to serialize.
What am I missing?
Thank you very much for any help or recommandations.
Nico