Boost-serialization: невозможно сериализовать указатель через базу без void_cast_register и register_type - PullRequest
0 голосов
/ 14 марта 2019

Мой вопрос очень похож на этот , но я делаю то же самое, и он не работает.

* КОНТЕКСТ *

Я использую вашу библиотеку сериализации с нескольких лет на Linux (GCC).Теперь я перехожу к окнам (_MSC_VER == 1600) (повышение 1.55, но те же проблемы, что и при повышении 1.69).

В моем примере я использую класс A в DLL, другой класс B наследуется отA в его DLL и исполняемый файл, связанный с этими DLL, который сериализует объект B, через его базу A.

Я делаю сериализуемый класс таким образом (я суммирую намеренно (без #include, ...)).Для A это то же самое, но у него нет базового класса.

------> Bh
Важным является использование BOOST_CLASS_EXPORT_KEY

#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
Важным является использование BOOST_SERIALIZATION_BASE_OBJECT_NVP и BOOST_CLASS_EXPORT_IMPLEMENT во включенном файле InstanciateSerializationTemplate.h

B::B() : i(123) {}

B::~B() {}

template <class Archive>
void B::serialize(Archive & ar, const unsigned int)
{
    ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ClassA);
    ar & BOOST_SERIALIZATION_NVP(i);
}

#define FULL_SCOPED_SERIALIZABLE_CLASS B
#include "Common/InstanciateSerializationTemplate.h"

-----> InstanciateSerializationTemplate.h
Целью этого файла является создание экземпляра методов шаблона B :: serialize для каждого типа архива и регистрация класса.Вот его содержание (еще раз, без имен и включения, чтобы его было легче читать):

// 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)

* МОЙ ВЫПУСК *

Все это работаетLinux, GCC, но не в Windows.

Если я напишу в моем exe-файле этот код сериализации:

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();

С этим кодом у меня есть archive_exception: "незарегистрированный класс - производный класс неЗарегистрировано или экспортировано ".

Я должен написать сериализацию так:

ar.register_type(static_cast<B*>(0));
boost::serialization::void_cast_register(static_cast<B*>(0), static_cast<A*>(0));
ar << SERIALIZE(a);

* ВОПРОС *

Наконец, мой вопрос: яне могу сделать так: чего бы я хотел добиться: когда новый класс станет сериализуемым, как описано выше, я ожидаю, что класс будет зарегистрирован автоматически (вероятно, с помощью BOOST_CLASS_EXPORT_IMPLEMENT в InstanciateSerializationTemplate.h).Слишком больно писать register_type и void_cast_register каждый раз, когда я хочу сериализоваться.

Чего мне не хватает?

Большое спасибо за любую помощь или рекомендации.

Нико

...