在哪里放置 BOOST_CLASS_EXPORT 进行 boost::serialization?
我正在尝试序列化指向多态类 Shape
的指针。所以我需要使用 BOOST_CLASS_EXPORT
宏 为每个子类定义一个GUID。问题是:放在哪里?
首先让我展示一个最小的测试用例:
shapes.hpp
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
class Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
// nothing to do
}
public:
virtual ~Shape() { }
};
class Rect : public Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
ar & boost::serialization::base_object<Shape>(*this);
}
public:
virtual ~Rect() { }
};
#ifdef EXPORT_IN_HEADER
BOOST_CLASS_EXPORT(Rect)
#endif
export.cpp
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_OBJECT
BOOST_CLASS_EXPORT(Rect)
#endif
main.cpp
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_MAIN
BOOST_CLASS_EXPORT(Rect)
#endif
int main() {
Shape *shape = new Rect();
boost::archive::text_oarchive ar(std::cout);
ar << shape;
}
在 gcc 上,我使用
g++ -omain main.cpp export.cpp -Wl,-Bstatic -lboost_serialization-mt -Wl,-Bdynamic -DEXPORT_IN_XXX
Here, export.cpp
可能看起来有点傻。在我的实际情况中,它包含一个使用 PIMPL 习惯用法的封闭类,并尝试序列化其(多态)Shape
实现。重要的一点是:BOOST_CLASS_EXPORT
可以位于与调用序列化的代码不同的对象文件中。
那么问题来了:在哪里使用BOOST_CLASS_EXPORT
?我有三个选项,可以使用 EXPORT_IN_XXX
宏启用。
EXPORT_IN_MAIN
有效,但不是我想要的。调用序列化的代码不需要了解 PIMPL 类的实现细节。EXPORT_IN_OBJECT
编译,但不起作用:它会导致boost::archive::archive_exception
并显示消息unregistered void cast
。根据文档,这应该可以通过使用boost::serialization::base_object
序列化基类来解决,就像我所做的那样,但这没有帮助。EXPORT_IN_HEADER
甚至无法编译。宏BOOST_CLASS_EXPORT
扩展为模板专业化(我们希望将其放在头文件中),而且还扩展为其中静态成员的定义。因此,我收到关于“boost::archive::detail::init_guid::guid_initializer”的多个定义的链接器错误。
如果重要的话,我正在使用 g++ 4.4.3 和 Boost 1.40。
I'm trying to serialize a pointer to a polymorphic class Shape
. So I need to use the BOOST_CLASS_EXPORT
macro to define a GUID for each subclass. The problem: where to put it?
Let me show a minimal test case first:
shapes.hpp
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
class Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
// nothing to do
}
public:
virtual ~Shape() { }
};
class Rect : public Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
ar & boost::serialization::base_object<Shape>(*this);
}
public:
virtual ~Rect() { }
};
#ifdef EXPORT_IN_HEADER
BOOST_CLASS_EXPORT(Rect)
#endif
export.cpp
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_OBJECT
BOOST_CLASS_EXPORT(Rect)
#endif
main.cpp
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_MAIN
BOOST_CLASS_EXPORT(Rect)
#endif
int main() {
Shape *shape = new Rect();
boost::archive::text_oarchive ar(std::cout);
ar << shape;
}
On gcc, I compile these with
g++ -omain main.cpp export.cpp -Wl,-Bstatic -lboost_serialization-mt -Wl,-Bdynamic -DEXPORT_IN_XXX
Here, export.cpp
may look a bit silly. In my actual situation, it contains an enclosing class that uses the PIMPL idiom, and tries to serialize its (polymorphic) Shape
implementation. The important point is: the BOOST_CLASS_EXPORT
could be in a different object file than the code that invokes the serialization.
So here's the problem: where to use BOOST_CLASS_EXPORT
? I have three options, which can be enabled using the EXPORT_IN_XXX
macros.
EXPORT_IN_MAIN
works, but is not what I want. The code invoking the serialization should not need to know about the implementation details of the PIMPL class.EXPORT_IN_OBJECT
compiles, but does not work: it results in aboost::archive::archive_exception
with the messageunregistered void cast
. According to the documentation, this should be solved by serializing base classes usingboost::serialization::base_object
, like I did, but it doesn't help.EXPORT_IN_HEADER
does not even compile. The macroBOOST_CLASS_EXPORT
expands to a template specialization (which we'd like to be in the header file), but also to the definitiof of a static member therein. So I get a linker error about amultiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'
.
If it matters, I'm using g++ 4.4.3 and Boost 1.40.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
导出 Boost 的类序列化。序列化文档 (1.44.0) 声明如下:
Exporting Class Serialization of the Boost.Serialization docs (1.44.0) states the following:
我最终将所有序列化代码放入标头
s11n.h
中,该标头包含在调用序列化的 CPP 文件中。本质上,就是我上面概述的EXPORT_IN_MAIN
场景,但在不同的文件中使用BOOST_CLASS_EXPORT
宏调用。当然,只有一个编译单元包含
s11n.h
时,这才有效,所以虽然它目前有效,但它不是真正的解决方案......I ended up putting all the serialization code in a header
s11n.h
that is included from the CPP file that invokes the serialization. Essentially, theEXPORT_IN_MAIN
scenario I sketched above, but with theBOOST_CLASS_EXPORT
macro invocations in a different file.This only works as long as only one compilation unit includes
s11n.h
, of course, so although it works for now, it's no real solution...您可以使用 EXPORT_IN_OBJECT,但包含 BOOST_CLASS_EXPORT 的文件还必须包含计划使用的所有存档 hpp 文件。
这是因为 BOOST_CLASS_EXPORT 宏注册了它认为您将使用的每个存档的派生类型信息(根据您包含的存档隐式确定)。
在您的示例中,使用 EXPORT_IN_OBJECT 但还要添加 #include
导出.cpp。
在我们的代码中,我们创建了 archives.hpp,其中包含我们使用的档案,并将其包含在我们需要使用 BOOST_CLASS_EXPORT 的地方。 (这样我们就有了一个正式的存档列表。)
缺点是,当我们决定使用新的存档类型时,我们需要重建所有内容,但我们发现这比多态存档支持更容易使用。
You can use EXPORT_IN_OBJECT but the file that contains BOOST_CLASS_EXPORT must also include all the archive hpp files that plan to use.
This is because the BOOST_CLASS_EXPORT macro registers the derived type information which each archive it thinks you will use (implicitly determined based upon which archives you have included.)
In your example, use EXPORT_IN_OBJECT but also add #include
to export.cpp.
In our code, we created archives.hpp that contains the archives we use and include it where ever we need to use BOOST_CLASS_EXPORT. (That way we have a single official list of archives.)
The downside is that we need to rebuild everything when we decide to use a new archive type, but we found that much easier to use than the polymorphic archive support.
查看这个旧线程。
http://lists.boost.org/boost-users/2005/ 01/9390.php
Check out this older thread.
http://lists.boost.org/boost-users/2005/01/9390.php
这个问题让我发疯,直到我意识到我的基类不是多态的。换句话说,它从未在任何地方使用过“虚拟”关键字。因为我不需要多态行为。
以下是我修复它的方法:
在派生类的 .cpp 文件中,我添加了以下内容:
这就是我必须做的全部事情。
This problem drove me insane until I realized that my base class was not polymorphic. In other words, it never used the keyword "virtual" anywhere. Because I didn't need polymorphic behavior.
Here is how I fixed it:
In my derived class's .cpp file, I added the following:
This is all that I had to do.
您可以为每个 .cpp 使用唯一的 BOOST_CLASS_EXPORT_GUID()
并仅将其添加到 .cpp 中。不是.h
you can use and unique BOOST_CLASS_EXPORT_GUID() for each .cpp
and add it only in the .cpp. not the .h