Поместите сериализацию класса в DLL - PullRequest
7 голосов
/ 08 февраля 2012

Я ищу (рабочий) пример для внешней сериализации структуры классов в DLL. В настоящее время я не могу найти никаких примеров для этого. В документации Boost просто говорится о некоторых макросах, форумы и группы новостей просто обсуждают конкретные проблемы с их решениями.

Итак, я прошу пример (внешне) сериализации структуры классов, как показано ниже. Наряду с кодом класса я добавил свой код для сериализации (который не работает, см. Внизу сообщение об ошибке).

class Foo
{
public:
    Foo() { number_ = 0; }
    virtual ~Foo() {}

    int getNumber() { return number_; }
    void setNumber( int var ) { number_ = var; }
private:
    int number_;
};

class Bar : public Foo
{
public:
    Bar() { doubleNumber_ = 0.0; }
    virtual ~Bar() {}

    double getDouble() { return doubleNumber_; }
    void setDouble( double var ) { doubleNumber_ = var; }

private:
    double doubleNumber_;
};

Все, что у меня есть, это код, подобный следующему:

serializeFoo.h

#ifndef _SERIALIZE_FOO_H_
#define _SERIALIZE_FOO_H_

#include "Foo.h"
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/version.hpp>

namespace boost {
namespace serialization {

template <typename Archive>
void save(Archive& ar, const Foo& object, const unsigned int version)
{
    ar << object.getNumber();
}

template <typename Archive>
void load(Archive& ar, Foo& object, const unsigned int version)
{
    int number;
    ar >> number;
    object.setNumber(number);
}

}} //namespace brackets

BOOST_SERIALIZATION_SPLIT_FREE( Foo )

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT_KEY( Foo )

#endif //_SERIALIZE_FOO_H_

serializeFoo.cpp

#include "serializeFoo.h"
BOOST_CLASS_EXPORT_IMPLEMENT( Foo )

serializeBar.h

#ifndef _SERIALIZE_BAR_H_
#define _SERIALIZE_BAR_H_

#include "Bar.h"
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/version.hpp>

namespace boost {
namespace serialization {

template <typename Archive>
void save(Archive& ar, const Bar& object, const unsigned int version)
{
    ar << base_object<Foo>(object);
    ar << object.getDouble();
}

template <typename Archive>
void load(Archive& ar, Bar& object, const unsigned int version)
{
    double doubleNumber;
    ar >> doubleNumber;
    object.setDouble(doubleNumber);
}

}} //namespace brackets

BOOST_SERIALIZATION_SPLIT_FREE( Bar )

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT_KEY( Bar )

#endif //_SERIALIZE_BAR_H_

serializeBar.cpp :

#include "serializeBar.h"
BOOST_CLASS_EXPORT_IMPLEMENT( Bar )

Код сериализации входит в DLL и должен использоваться в другом проекте с использованием классов Foo и Bar. Все компилируется нормально, но во время выполнения я получаю сообщение
unregistered class - derived class not registered or exported

Так я использовал неправильные макросы? Я скучаю по макросу? Правильный ли приведенный выше код или есть какая-то структурная ошибка? Возможно, это может быть полезно и для многих других людей, я не думаю, что помещать сериализацию класса в DLL очень экзотично ...

Ответы [ 4 ]

2 голосов
/ 12 марта 2015

Недавно я столкнулся с подобной проблемой, спустя 3 года после того, как был задан этот вопрос. Я наконец нашел способ обойти это. В приведенном выше примере.

  • Bar является подклассом Foo, поэтому он должен быть зарегистрирован / экспортирован;
  • serializeFoo.cpp создает экземпляр шаблона класса GUID для регистрации / экспорта Foo;
  • serializeBar.cpp создает экземпляр шаблона класса GUID для регистрации / экспорта Bar;
  • Соблюдаются правила включения всех необходимых типов архивов перед экспортом ключей классов;
  • Обе единицы перевода связаны вместе для создания DLL.

Я предполагаю, что в вашем exe-файле, когда вы пытаетесь сериализовать указатель Foo*, указывающий на объект Bar, вы получили ошибку "незарегистрированный класс, бла-бла". Это связано с тем, что Boost.Serialization как-то неправильно генерирует GUID для класса Bar до , вызывается функция сериализации.

Я не знаю, почему это происходит, но кажется, что GUID генерируется ленивым образом - если не используется ни один из символов из единицы перевода serializeBar.cpp, ни один из кода создания / инициализации, определенного в этом Будет выполнен перевод блока - который включает в себя класс регистрации / экспорта Bar.

Чтобы доказать это, вы можете попробовать использовать (фиктивный) символ в serializeBar.cpp (например, вызвав фиктивную функцию, реализованную в serializeBar.cpp) перед вызовом любой функции сериализации для Foo*. Вопрос должен исчезнуть.

Надеюсь, это поможет.

1 голос
/ 07 июля 2012

набор тестов и демонстрационная программа, поставляемая с библиотекой сериализации, демонстрируют именно эту возможность. Поэтому сначала убедитесь, что это работает. Тогда сравните свой пример с ним.

Роберт Рами

"Честно говоря, ИМХО, в некоторые моменты, Boost Serialization пересекает границы того, что надежно возможно с чистой моделью сборки c ++ без внешних инструментов ..."

хмммммм - значит, он пересекает границу, как это возможно? Вы в значительной степени правы, хотя. Большие усилия были потрачены на реализацию всего, что считалось необходимым для того, чтобы такой пакет был приемлемым для повышения.

RR

0 голосов
/ 17 декабря 2012

Используйте BOOST_CLASS_EXPORT для регистрации всех ваших классов, которые вы хотите сериализовать

0 голосов
/ 15 февраля 2012

Трудно сказать ... Есть много шансов, что что-то пойдет не так. Я рекомендую скачать тестовый код для ускоренной сериализации (www.boost.org/doc/libs/1_48_0/libs/serialization/test/). Взгляните на контрольные примеры для Ah, A.cpp и dll_a.cpp (которые в основном тестируют ваш сценарий) и попытайтесь заставить его работать вне системы буст-тестов: используйте вашу среду сборки, попробуйте изменить параметры компилятора / компоновщика так, чтобы Подберите те из набора тестов повышения для вашего набора инструментов.

Честно говоря, ИМХО, в некоторые моменты, Boost Serialization пересекает границы того, что надежно возможно с чистой моделью сборки c ++ без внешних инструментов ...

...