Boost logo

Boost :

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


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