在哪里放置BOOST_CLASS_EXPORT用于boost :: serialization?

时间:2010-08-03 12:16:22

标签: c++ boost-serialization

我正在尝试序列化指向多态类Shape的指针。所以我需要使用BOOST_CLASS_EXPORT macro为每个子类定义一个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

在这里,export.cpp可能看起来有点傻。在我的实际情况中,它包含一个使用PIMPL惯用语的封闭类,并尝试序列化其(多态)Shape实现。重要的是:BOOST_CLASS_EXPORT可能位于不同的目标文件中,而不是调用序列化的代码。

所以这就是问题:在哪里使用BOOST_CLASS_EXPORT?我有三个选项,可以使用EXPORT_IN_XXX宏启用。

  1. EXPORT_IN_MAIN有效,但不是我想要的。调用序列化的代码不需要知道PIMPL类的实现细节。

  2. EXPORT_IN_OBJECT编译,但不起作用:它会生成boost::archive::archive_exception消息unregistered void cast。根据{{​​3}},这应该通过使用boost::serialization::base_object序列化基类来解决,就像我一样,但它没有帮助。

  3. EXPORT_IN_HEADER甚至没有编译。宏BOOST_CLASS_EXPORT扩展为模板特化(我们希望在头文件中),但也扩展到其中的静态成员的定义。所以我收到关于multiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'

  4. 的链接器错误

    如果重要,我正在使用g ++ 4.4.3和Boost 1.40。

6 个答案:

答案 0 :(得分:8)

Boost.Serialization docs(1.44.0)的

Exporting Class Serialization声明如下:


  

BOOST_CLASS_EXPORT同样如此   源模块,包括任何一个   归档类头将实例化   代码[...]

     

注意这个的实现   功能要求   出现BOOST_CLASS_EXPORT宏   之后并包含任何存档   代码所在的类头   实例化。所以,使用的代码   BOOST_CLASS_EXPORT看起来像   以下内容:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
... // other archives

#include "a.hpp" // header declaration for class a
BOOST_CLASS_EXPORT(a)
... // other class headers and exports
  

[...]包括BOOST_CLASS_EXPORT   “a.hpp”标题就像人们一样   做其他序列化特征   将使困难或不可能   遵循上述规则   之前包含归档标头   调用BOOST_CLASS_EXPORT。这个   可以通过使用最好地解决   标题中为BOOST_CLASS_EXPORT_KEY   声明和BOOST_CLASS_EXPORT_IMPLEMENT在   类定义文件。


答案 1 :(得分:5)

我最终将所有序列化代码放在标头s11n.h中,该标头包含在调用序列化的CPP文件中。基本上,我在上面概述了EXPORT_IN_MAIN场景,但在不同文件中使用BOOST_CLASS_EXPORT宏调用。

只有当只有一个编译单元包含s11n.h时才会起作用,所以虽然它现在有用,但它并不是真正的解决方案......

答案 2 :(得分:2)

您可以使用EXPORT_IN_OBJECT,但包含BOOST_CLASS_EXPORT的文件还必须包含计划使用的所有归档hpp文件。

这是因为BOOST_CLASS_EXPORT宏注册了它认为您将使用的每个存档的派生类型信息(根据您包含的存档隐式确定)。

在您的示例中,使用EXPORT_IN_OBJECT但也添加#include to export.cpp。

在我们的代码中,我们创建了archives.hpp,其中包含我们使用的档案,并将其包含在我们需要使用BOOST_CLASS_EXPORT的地方。 (这样我们就有一份正式的档案清单。)

缺点是当我们决定使用新的存档类型时,我们需要重建所有内容,但我们发现它比多态存档支持更容易使用。

答案 3 :(得分:1)

答案 4 :(得分:0)

您可以为每个.cpp使用和唯一的BOOST_CLASS_EXPORT_GUID() 并仅在.cpp中添加它。不是.h

答案 5 :(得分:0)

这个问题让我疯狂,直到我意识到我的基类不是多态的。换句话说,它从未在任何地方使用关键字“虚拟”。因为我不需要多态行为。

以下是我修复它的方法:

  1. 我刚刚在我的基类中的一些随机方法上打了关键字“virtual”。
  2. 在我的派生类的.cpp文件中,我添加了以下内容:

    #include <boost/serialization/export.hpp>
    BOOST_CLASS_EXPORT(testnamespace::derivedclass)
    
  3. 这就是我必须做的一切。