将类的序列化放入DLL中

时间:2012-02-08 07:02:27

标签: c++ dll boost-serialization

我正在寻找一个(工作)示例,用于外部序列化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 个答案:

答案 0 :(得分:2)

最近,在问到这个问题3年后,我遇到了类似的问题。我终于找到了解决它的解决方法。在上面的例子中。

  • BarFoo的子类,因此必须注册/导出;
  • serializeFoo.cpp实例化GUID模板类以注册/导出Foo;
  • serializeBar.cpp实例化GUID模板类以注册/导出Bar;
  • 遵守在导出类密钥之前包含所有必需的归档类型的规则;
  • 两个翻译单元都链接在一起以创建DLL。

我假设在你的exe中,当你试图序列化指向Foo*对象的Bar指针时,你得到了#34;未注册的类blahblah&#34;错误。这是因为在调用序列化函数之前,Boost.Serialization以某种方式无法为类Bar 正确生成GUID。

我不知道为什么会发生这种情况,但似乎GUID是以懒惰的方式生成的 - 如果没有使用翻译单元serializeBar.cpp的符号,则没有实例化/初始化将执行该翻译单元中定义的代码 - 包括Bar的类注册/导出。

为了证明这一点,您可以尝试在serializeBar.cpp中使用(虚拟)符号(例如,通过调用serializeBar.cpp中实现的虚函数),然后再调用Foo*的任何序列化函数。问题应该消失。

希望它有所帮助。

答案 1 :(得分:1)

与序列化库一起分发的测试套件和演示证明了这个功能。所以首先要确保有效。然后将你的例子与它进行比较。

Robert Ramey

“老实说,恕我直言,在某些方面,Boost Serialization跨越了纯粹的c ++构建模型与外部工具可靠的边界......”

嗯嗯 - 所以它可能会越过寄宿生?不过,你在精神上几乎是正确的。我们付出了巨大的努力来实现所有被认为是必要的东西,以使这种包装成为可以接受的。

RR

答案 2 :(得分:0)

很难说......事情有很多机会出错。我建议下载boost序列化的测试代码(www.boost.org/doc/libs/1_48_0/libs/serialization/test/)。看看围绕Ah,A.cpp和dll_a.cpp(基本上测试你的场景)的测试用例,并尝试使其在boost测试系统之外工作:使用你的构建环境,尝试修改编译器/链接器选项与您的工具集的boost测试套件相匹配。

老实说,恕我直言,在某些方面,Boost Serialization跨越了纯粹的c ++构建模型与外部工具可靠的边界......

答案 3 :(得分:0)

使用BOOST_CLASS_EXPORT注册您要序列化的所有课程