Boost logo

Boost :

Subject: Re: [boost] Cannot serialize pointer through base without void_cast_register and register_type.
From: Nicolas Guillot (nicolas.guillot_at_[hidden])
Date: 2019-03-14 18:01:58


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 <nicolas.guillot_at_[hidden]>
wrote:

> 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>(binary_iarchive
> & ar, const unsigned int version);
> template __declspec(dllexport) void
> FULL_SCOPED_SERIALIZABLE_CLASS::serialize<binary_oarchive>(binary_oarchive
> & ar, const unsigned int version);
> // XML:
> template __declspec(dllexport) void
> FULL_SCOPED_SERIALIZABLE_CLASS::serialize<xml_iarchive>(xml_iarchive & ar,
> const unsigned int version);
> template __declspec(dllexport) void
> FULL_SCOPED_SERIALIZABLE_CLASS::serialize<xml_oarchive>(xml_oarchive & ar,
> const unsigned int version);
> // TXT:
> template __declspec(dllexport) void
> FULL_SCOPED_SERIALIZABLE_CLASS::serialize<text_iarchive>(text_iarchive &
> ar, const unsigned int version);
> template __declspec(dllexport) void
> FULL_SCOPED_SERIALIZABLE_CLASS::serialize<text_oarchive>(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<B*>(0));
> boost::serialization::void_cast_register(static_cast<B*>(0),
> static_cast<A*>(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
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk