将类的序列化放入DLL中

发布于 2025-01-03 07:38:53 字数 2942 浏览 1 评论 0原文

我正在寻找一个(工作)示例,用于在 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 的项目中使用。一切都编译正常,但在运行时我收到消息
未注册的类 - 未注册或导出的派生类

那么我使用了错误的宏吗?我错过了宏吗?上面的代码正确还是存在某种结构错误?也许这对很多其他人也有用,我不认为将类的序列化放入 DLL 中是非常奇特的......

I'm looking for a (working) example for externally serializing a class-structure in a DLL. Currently I'm not able to find any examples for that. The Boost documentation is just stating some macros, the forums and newsgroups are just discussing specific problems with their solutions.

So I'm asking for an example for (externally) serializing a class-structure like the following. Along with the class-code I added some code of mine for serializing (which does not work, see bottom for error-message).

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_;
};

All what I've got so far is code like this:

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 )

The serialization-code goes into a DLL and should be used in another project using classes Foo and Bar. Everything compiles fine, but at runtime I get the message
unregistered class - derived class not registered or exported

So did I used the wrong macros? Do I miss a macro? Is the above code right or is there some kind of structural error? Perhaps this could be useful for a lot of other people too, I don't think that putting the serialization of a class into a DLL is very exotic...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无尽的现实 2025-01-10 07:38:53

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

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

我假设在您的 exe 中,当您尝试序列化指向 Bar 对象的 Foo* 指针时,您会收到“未注册类 blahblah”错误。这是因为在调用序列化函数之前,Boost.Serialization 无法正确生成类 Bar 的 GUID。

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

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

希望有帮助。

I ran into a similar issue recently, 3 years after this question was asked. I finally found out a workaround to solve it. In the example above.

  • Bar is a subclass of Foo, so it must be registered/exported;
  • serializeFoo.cpp instantiates a GUID template class to register/export Foo;
  • serializeBar.cpp instantiates a GUID template class to register/export Bar;
  • The rules to include all necessary archive types before exporting the class keys are respected;
  • Both translation units are linked together to create a DLL.

I assume in your exe, while you are trying to serialise a Foo* pointer pointing to a Bar object, you got the "unregistered class blahblah" error. This is because Boost.Serialization somehow does not properly generate a GUID for class Bar before the serialize function is called.

I don't know why this happens, but it seems that GUID is generated in a lazy way -- if none of the symbols from the translation unit serializeBar.cpp is used, none of the instantiation/initialization code defined in that translation unit will be performed -- that includes the class registration/exportation of Bar.

To prove that, you can try to use a (dummy) symbol in serializeBar.cpp (e.g. by calling a dummy function implemented in serializeBar.cpp) before calling any serialization function for Foo*. The issue should disappear.

Hope it helps.

香草可樂 2025-01-10 07:38:53

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

Robert Ramey

“老实说,恕我直言,在某些方面,Boost Serialization 跨越了纯 C++ 构建模型(无需外部工具)可靠可能的边界……”

嗯嗯 - 所以它跨越了可能的边界?不过,你在精神上几乎是正确的。为了让这样的包能够被 boost 接受,我们付出了巨大的努力来实现所有被认为必要的东西。

RR

the test suite and demo distributed with the serialization library demonstrate exactly this facility. So first make sure that works. Then compare your example to it.

Robert Ramey

"Honestly, IMHO, at some points, Boost Serialization crosses the border of what is reliably possible with pure c++ build model w/o external tools..."

hmmmmmm - so it crosses the boarder as what's possible? You're pretty much correct in spirit though. Great effort was expended to implement everything that was considered necessary for such a package to be acceptable into boost.

RR

情绪失控 2025-01-10 07:38:53

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

老实说,恕我直言,在某些方面,Boost Serialization 跨越了纯 C++ 构建模型(无需外部工具)可靠可能的边界......

Hard to tell... There are many chances for things to go wrong. I recommend to download the test code for boost serialization (www.boost.org/doc/libs/1_48_0/libs/serialization/test/). Have a look at the test cases around A.h, A.cpp and dll_a.cpp (which basically test your scenario) and try to make it work outside of the boost test system: use your build environment, try to modify compiler/linker options to match those of boost test suite for your toolset.

Honestly, IMHO, at some points, Boost Serialization crosses the border of what is reliably possible with pure c++ build model w/o external tools...

余生一个溪 2025-01-10 07:38:53

使用 BOOST_CLASS_EXPORT 注册您想要序列化的所有类

Use BOOST_CLASS_EXPORT to register all your classes which you would like to serialize

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文