Boost 序列化多态寄存器(导出)无法跨文件工作

发布于 2024-12-11 11:00:09 字数 9347 浏览 0 评论 0原文

我在我的项目中使用 boost::serialization 。该项目很大,并且在多个地方序列化我的对象。根据此处的文档,我应该用两个单独的步骤导出我的课程。

  1. .h 文件中的 BOOST_EXPORT_KEY() 包含声明。
  2. .cpp 文件中的 BOOST_EXPOET_IMPLMENT() 包含导出的实例化(定义)。

hier.h 类层次结构,层次结构中有3个类。

/*
B <---+--- D1
      |
      +--- D2
*/

#include <boost/serialization/base_object.hpp>                                                                                                                                                                 

class B {                                                                                                                                                                                                      
public:                                                                                                                                                                                                        
    virtual ~B() {}                                                                                                                                                                                            
    template < typename Ar >                                                                                                                                                                                   
    void serialize(Ar& ar, const int) {                                                                                                                                                                        
    }                                                                                                                                                                                                          
} ;                                                                                                                                                                                                            

class D1 : public B {                                                                                                                                                                                          
public:                                                                                                                                                                                                        
    virtual ~D1() {}                                                                                                                                                                                           
    template < typename Ar > void serialize(Ar& ar, const int) {                                                                                                                                               
        boost::serialization::base_object<B>(*this);                                                                                                                                                           
    }                                                                                                                                                                                                          
} ;                                                                                                                                                                                                            

class D2 : public B {                                                                                                                                                                                          
public:                                                                                                                                                                                                        
    template < typename Ar > void serialize(Ar& ar, const int) {                                                                                                                                               
        boost::serialization::base_object<B>(*this);                                                                                                                                                           
    }                                                                                                                                                                                                          
    virtual ~D2() {}                                                                                                                                                                                           
} ;                                                                                                                                                                                                            

#include <boost/serialization/export.hpp>                                                                                                                                                                      

BOOST_CLASS_EXPORT_KEY(B);                                                                                                                                                                                     
BOOST_CLASS_EXPORT_KEY(D1);                                                                                                                                                                                    
BOOST_CLASS_EXPORT_KEY(D2);

并且 hier.cpp 包含实现:

#include <boost/serialization/export.hpp>
#include "hier.h"

BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);

并且 main.cpp 使用序列化:

#include <iostream>                                                                                                                                                                                            
#include <sstream>                                                                                                                                                                                             
#include <boost/archive/text_iarchive.hpp>                                                                                                                                                                     
#include <boost/archive/text_oarchive.hpp>                                                                                                                                                                     
#include <boost/serialization/export.hpp>                                                                                                                                                                      
#include "hier.h"                                                                                                                                                                                              

int main(int argc, char* argv[])                                                                                                                                                                               
{                                                                                                                                                                                                              
    B* d1 = new D1();                                                                                                                                                                                          
    B* d2 = new D2();                                                                                                                                                                                          
    std::ostringstream os;                                                                                                                                                                                     
    boost::archive::text_oarchive oa (os);                                                                                                                                                                     
    oa & d1 & d2;                                                                                                                                                                                              
}

编译没有任何问题,但运行它会导致:

terminate called after throwing an instance of 'boost::archive::archive_exception'
  what():  unregistered class - derived class not registered or exported

这意味着派生类是未注册,意味着 hier.cpp 中的注册不起作用。但这确实很奇怪,因为:

  1. 如果我注册实现既是 main.cpp 又是 hier.cpp,它会在链接时发出重复的定义。 意味着hier.cpp中的注册是可以的,并且暴露在链接器可见性中。,否则不会出现重复定义错误。

  2. 如果我仅在 main.cpp 中注册实现,则运行正常。

在那种情况下我真的很困惑。如有任何意见和建议,我们将不胜感激。提前致谢。

I am using boost::serialization in my project. The project is large, and serializes my objects in several places. According to the documentation here, I should export my class with two separated step.

  1. BOOST_EXPORT_KEY() in .h file, witch contains the declaration.
  2. BOOST_EXPOET_IMPLEMENT() in .cpp file, witch contains the instantiation(definition) of the exporting.

hier.h the class hierarchy, there are 3 classes in the hierarchy.

/*
B <---+--- D1
      |
      +--- D2
*/

#include <boost/serialization/base_object.hpp>                                                                                                                                                                 

class B {                                                                                                                                                                                                      
public:                                                                                                                                                                                                        
    virtual ~B() {}                                                                                                                                                                                            
    template < typename Ar >                                                                                                                                                                                   
    void serialize(Ar& ar, const int) {                                                                                                                                                                        
    }                                                                                                                                                                                                          
} ;                                                                                                                                                                                                            

class D1 : public B {                                                                                                                                                                                          
public:                                                                                                                                                                                                        
    virtual ~D1() {}                                                                                                                                                                                           
    template < typename Ar > void serialize(Ar& ar, const int) {                                                                                                                                               
        boost::serialization::base_object<B>(*this);                                                                                                                                                           
    }                                                                                                                                                                                                          
} ;                                                                                                                                                                                                            

class D2 : public B {                                                                                                                                                                                          
public:                                                                                                                                                                                                        
    template < typename Ar > void serialize(Ar& ar, const int) {                                                                                                                                               
        boost::serialization::base_object<B>(*this);                                                                                                                                                           
    }                                                                                                                                                                                                          
    virtual ~D2() {}                                                                                                                                                                                           
} ;                                                                                                                                                                                                            

#include <boost/serialization/export.hpp>                                                                                                                                                                      

BOOST_CLASS_EXPORT_KEY(B);                                                                                                                                                                                     
BOOST_CLASS_EXPORT_KEY(D1);                                                                                                                                                                                    
BOOST_CLASS_EXPORT_KEY(D2);

And a hier.cpp contains the implementation:

#include <boost/serialization/export.hpp>
#include "hier.h"

BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);

And a main.cpp use the serialization:

#include <iostream>                                                                                                                                                                                            
#include <sstream>                                                                                                                                                                                             
#include <boost/archive/text_iarchive.hpp>                                                                                                                                                                     
#include <boost/archive/text_oarchive.hpp>                                                                                                                                                                     
#include <boost/serialization/export.hpp>                                                                                                                                                                      
#include "hier.h"                                                                                                                                                                                              

int main(int argc, char* argv[])                                                                                                                                                                               
{                                                                                                                                                                                                              
    B* d1 = new D1();                                                                                                                                                                                          
    B* d2 = new D2();                                                                                                                                                                                          
    std::ostringstream os;                                                                                                                                                                                     
    boost::archive::text_oarchive oa (os);                                                                                                                                                                     
    oa & d1 & d2;                                                                                                                                                                                              
}

It compiled without any problem, but run it will cause:

terminate called after throwing an instance of 'boost::archive::archive_exception'
  what():  unregistered class - derived class not registered or exported

Which means the derived class is not registered, means the registration in the hier.cpp is not working. But that is really strange, because:

  1. If I register implementation is both main.cpp and hier.cpp, it issue duplicated definition while linking. Means the registration in hier.cpp is OK and is exposed into the linkers visibility., otherwise there will be no duplicated definition error.

  2. If I register implementation only in main.cpp, it runs OK.

I am really confused in that situation. Any comment and suggestion is appreciated. Thanks in advance.

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

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

发布评论

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

评论(1

り繁华旳梦境 2024-12-18 11:00:09

在调用 BOOST_CLASS_EXPORT_* 之前,您应该包含要使用的存档。然后,宏为标头添加特定的序列化函数。

这意味着您应该将 hier.cpp 中的代码更改为以下内容:

#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "hier.h"

BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);

hier.h 中的代码相应更改:

#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

BOOST_CLASS_EXPORT_KEY(B);
BOOST_CLASS_EXPORT_KEY(D1);
BOOST_CLASS_EXPORT_KEY(D2);

来源:
Boost 序列化文档

PS:< br>
我不知道这是否能解决您的问题,但我认为这可能会造成一些麻烦。我认为值得一试。

Before calling BOOST_CLASS_EXPORT_* you should include the archives which you want to use. The maсro then adds specific serialize-functions for the headers.

This means you should change your code in hier.cpp to the following:

#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "hier.h"

BOOST_CLASS_EXPORT_IMPLEMENT(D1);
BOOST_CLASS_EXPORT_IMPLEMENT(D2);

The code in hier.h changes accordingly:

#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

BOOST_CLASS_EXPORT_KEY(B);
BOOST_CLASS_EXPORT_KEY(D1);
BOOST_CLASS_EXPORT_KEY(D2);

Sources:
Boost Serialization Documentation

PS:
I do not know if this is solving your problem, but I think it could be causing some trouble. I think it's worth a try.

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