C++ Boost.serialization未注册类异常,在运行时链接的共享库中定义了序列化类

C++ Boost.serialization未注册类异常,在运行时链接的共享库中定义了序列化类,c++,serialization,boost,dynamic-linking,boost-serialization,C++,Serialization,Boost,Dynamic Linking,Boost Serialization,我正在尝试创建一个模块化的游戏系统,我希望用户定义的类能够被序列化。为此,我放置了从多态基类派生的类。我试图在这个类上实现序列化时遇到了麻烦。我不断得到未注册的类异常(运行时错误) 下面是一个最小的测试用例: 环境:windows 8.1 MSVC++12(visual studio 2013) h——定义多态的父类 #pragma once #include <boost/serialization/access.hpp> #include <boost/serializa

我正在尝试创建一个模块化的游戏系统,我希望用户定义的类能够被序列化。为此,我放置了从多态基类派生的类。我试图在这个类上实现序列化时遇到了麻烦。我不断得到未注册的类异常(运行时错误)

下面是一个最小的测试用例:

环境:windows 8.1 MSVC++12(visual studio 2013)

h——定义多态的父类

#pragma once

#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>

class parent_class
{

protected:

    friend boost::serialization::access;

    template <typename Archive>
    void serialize(Archive& ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(x) & BOOST_SERIALIZATION_NVP(y);
    }

    float x;
    float y;

public:

    explicit parent_class(float x, float y) : x(x), y(y) {}

    // virtual deconstructor to make it polymorphic
    virtual ~parent_class()
    {
    }
};

BOOST_CLASS_EXPORT(parent_class);
#pragma一次
#包括
#包括
#包括
类父类
{
受保护的:
friend boost::serialization::access;
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar和BOOST_序列化_NVP(x)和BOOST_序列化_NVP(y);
}
浮动x;
浮动y;
公众:
显式父类(float x,float y):x(x),y(y){
//虚拟解构器,使其多态
虚拟~parent_类()
{
}
};
增强类导出(父类);
Main.cpp-在.exe中唯一的.cpp

#include "parent_class.h"

#include <boost/archive/xml_oarchive.hpp>

#include <fstream>
#include <iostream>

#include <Windows.h>

typedef parent_class* addChildFun(float, float, float);

int main()
{
    // acquire module
    HMODULE module = LoadLibraryA("SerializationDLL.dll");
    assert(module);

    // acquire function ptr
    FARPROC addChildRaw = GetProcAddress(module, "makeChild");
    assert(addChildRaw);
    addChildFun* addChildPtr = reinterpret_cast<addChildFun*>(addChildRaw);

    // make polymorphic pointer
    parent_class* child = addChildPtr(325.f, 214.f, 2.5f);

    // INIT BOOST SERIALIZIZATION ARCHIVE
    std::ofstream stream{ "file.txt" };
    boost::archive::xml_oarchive arch{ stream };

    try
    {

        arch << BOOST_SERIALIZATION_NVP(child);

    }
    catch (std::exception& e)
    {
        std::cout << e.what(); // prints "unregistered class - derived class not registered or exported
    }


    std::cin.get();
    delete child;
}
#包括“parent_class.h”
#包括
#包括
#包括
#包括
typedef parent_class*addChildFun(浮点、浮点、浮点);
int main()
{
//获取模块
HMODULE module=LoadLibraryA(“SerializationDLL.dll”);
断言(模块);
//获取函数ptr
FARPROC addChildRaw=GetProcAddress(模块“makeChild”);
断言(addChildRaw);
addChildFun*addChildPtr=重新解释(addChildRaw);
//生成多态指针
父类*child=addChildPtr(325.f,214.f,2.5f);
//初始化BOOST序列化存档
std::of流流{“file.txt”};
boost::archive::xml_oarchive arch{stream};
尝试
{

arch好的,经过艰苦的努力,我找到了解决方案,它存在于两行代码中


问题似乎是存储类GUID和实现之间关联的映射被定义了两次,因为它位于.dll和.exe都链接到的.lib文件中。解决此问题的明显方法是使用Boost.serialization库的动态链接支持

如何使用它是在使用序列化库的每个.cpp文件的开头放置一个
#define BOOST\u SERIALIZATION\u DYN\u LINK 1
。这样,代码只实例化一次,BOOST可以在映射中找到类。

问题似乎是存储类GUID和实现之间关联的映射被定义了两次,因为它位于.dll和.exe都链接到的.lib文件中。解决这个问题的明显方法是使用Boost.serialization库的动态链接支持

这个问题实际上是静态链接工作方式的问题。强制DLL版本的解决方案可以工作,但不是最好的。 不使用内联序列化函数可以更好地解决这个问题

template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
    ar & boost::serialization::make_nvp("owner", boost::serialization::base_object<parent_class>(*this));
    ar & BOOST_SERIALIZATION_NVP(z);
}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::make_nvp(“所有者”,boost::serialization::base_对象(*this));
ar&BOOST_序列化_NVP(z);
}

模板
无效序列化(存档&ar,常量未签名整数版本);
并包含在您的孩子*.cpp文件中

template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
    ar & boost::serialization::make_nvp("owner", boost::serialization::base_object<parent_class>(*this));

    ar & BOOST_SERIALIZATION_NVP(z);
}
template child_class::serialize<boost::archive::text_oarchive>;
template child_class::serialize<boost::archive::text_iarchive>;
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::make_nvp(“所有者”,boost::serialization::base_对象(*this));
ar&BOOST_序列化_NVP(z);
}
模板子类::序列化;
模板子类::序列化;
换句话说-避免使用内联函数。这将保证您将获得一个且仅一个序列化函数的实例化。这将适用于静态和共享库生成。它还将消除有时因违反“一个定义规则”而引起的混淆


顺便说一句,不要在源文件中添加e#define BOOST_SERIALIZATION_DYN_LINK 1之类的内容,而是通过make或project文件在编译器命令行中添加。这样,您就可以保留将代码用作静态库、共享库或直接导入项目的功能。

这是否适用于编译时未定义的类,但在运行时,如果是动态链接的DLL或其他文件?简而言之,exe无法知道DLL中的类,因为我试图编写一个真正的模块化系统。我试图实现这一点,但似乎无法实现。我不确定您的解决方案会带来什么。child_类中的序列化函数在两次实例化时是否存在问题ce,因为它位于一个不包含在任何地方的.cpp文件中,还是父类实例化两次的问题?
template <typename Archive>
void serialize(Archive& ar, const unsigned int version);
template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
    ar & boost::serialization::make_nvp("owner", boost::serialization::base_object<parent_class>(*this));

    ar & BOOST_SERIALIZATION_NVP(z);
}
template child_class::serialize<boost::archive::text_oarchive>;
template child_class::serialize<boost::archive::text_iarchive>;