gpt4 book ai didi

c++ - 在 dll 中定义的派生嵌套类的序列化

转载 作者:太空宇宙 更新时间:2023-11-04 13:45:27 24 4
gpt4 key购买 nike

很多天以来,我一直在尝试解决派生嵌套类的 dll 序列化问题。我已经尝试了很多我发现的例子(即 export_keys ),但我总是遇到运行时错误。访问序列化函数存在一些问题。我写了一个简化的类,类似于我们根据 boost serialization tests (polymorphic_derived2) 使用的类.

//#############dll ###################

//PlugInClass_Derived_2.h//

#pragma once

#ifdef PLUGIN
// All functions in this file are exported
#else
// All functions in this file are imported
#define PLUGIN __declspec(dllimport)
#endif

#include "PlugInClass_Derived_1.h"

class PlugInClass_Derived_2 : public PlugInClass_Derived_1
{
public:

class DLL_DECL(BOOST_PP_EMPTY()) Parameter : public PlugInClass_Derived_1::Parameter
{
public:

Parameter(void);
virtual ~Parameter(void){};

private:
friend class boost::serialization::access;

template <typename Archive>
void serialize(Archive &ar, const unsigned int version);

public:
virtual const char * get_key() const {
return "PlugInClass_Derived_2_Parameter";
}
};

public:

/** @brief standard constructor */
PlugInClass_Derived_2(){};
virtual ~PlugInClass_Derived_2(){};

PLUGIN virtual boost::shared_ptr<PlugInClass_Base::Parameter> getInitParameter();
};



extern "C" PLUGIN PlugInClass_Base* Create(/*void** params, const int number*/);
extern "C" PLUGIN void Destroy(PlugInClass_Base* p);

// we use this because we want to assign a key to this type
// but we don't want to explicitly instantiate code every time
// we do so!!!. If we don't do this, we end up with the same
// code in BOTH the DLL which implements polymorphic_derived2
// as well as the main program.
BOOST_CLASS_EXPORT_KEY(PlugInClass_Derived_2::Parameter)

// note the mixing of type_info systems is supported.
BOOST_CLASS_TYPE_INFO(
PlugInClass_Derived_2::Parameter,
boost::serialization::extended_type_info_typeid<PlugInClass_Derived_2::Parameter>
)

#undef DLL_DECL

//PlugInClass_Derived_2.cpp

/* boost headers go here */

/* plugin headers go here */
#define POLYMORPHIC_DERIVED2_EXPORT
#include "PlugInClass_Derived_2.h"

PlugInClass_Derived_2::Parameter::Parameter(){
d = -2.;
/*nothing*/
}

template <typename Archive>
void PlugInClass_Derived_2::Parameter::serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<PlugInClass_Derived_1::Parameter>(*this);
}

boost::shared_ptr<PlugInClass_Base::Parameter> PlugInClass_Derived_2::getInitParameter(){
// get local data pointer;
boost::shared_ptr<PlugInClass_Base::Parameter> localParameter(new PlugInClass_Derived_2::Parameter());
// update parent information

// return local data
return localParameter;
}


PlugInClass_Base* Create(/*void** params, const int number*/) {
return new PlugInClass_Derived_2();
}


void Destroy(PlugInClass_Base* p) {
delete p;
}



// instantiate code for text archives
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

template EXPORT_DECL(void) PlugInClass_Derived_2::Parameter::serialize(
boost::archive::text_oarchive & ar,
const unsigned int version
);
template EXPORT_DECL(void) PlugInClass_Derived_2::Parameter::serialize(
boost::archive::text_iarchive & ar,
const unsigned int version
);

// instantiate code for polymorphic archives
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>

template EXPORT_DECL(void) PlugInClass_Derived_2::Parameter::serialize(
boost::archive::polymorphic_oarchive & ar,
const unsigned int version
);
template EXPORT_DECL(void) PlugInClass_Derived_2::Parameter::serialize(
boost::archive::polymorphic_iarchive & ar,
const unsigned int version
);


// MWerks users can do this to make their code work
BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(
PlugInClass_Derived_1::Parameter
, PlugInClass_Derived_2::Parameter)

// note: export has to be AFTER #includes for all archive classes
BOOST_CLASS_EXPORT_IMPLEMENT(PlugInClass_Derived_2::Parameter)

//PlugInClass_Derived_1.h

#pragma once

#ifdef PLUGIN
// All functions in this file are exported
#else
// All functions in this file are imported
#define PLUGIN __declspec(dllimport)
#endif

#include "PlugInClass_Base.h"

class PlugInClass_Derived_1 : public PlugInClass_Base
{
public:

class DLL_DECL(BOOST_PP_EMPTY()) Parameter : public PlugInClass_Base::Parameter
{
public:

int a, b, c;

Parameter(void);
virtual ~Parameter(void){};

private:
friend class boost::serialization::access;

template <typename Archive>
void serialize(Archive &ar, const unsigned int version);

public:
virtual const char * get_key() const {
return "PlugInClass_Derived_1_Parameter";
}
};

public:

/** @brief standard constructor */
PlugInClass_Derived_1(){};
virtual ~PlugInClass_Derived_1(){};

virtual boost::shared_ptr<PlugInClass_Base::Parameter> getInitParameter();
};


// we use this because we want to assign a key to this type
// but we don't want to explicitly instantiate code every time
// we do so!!!. If we don't do this, we end up with the same
// code in BOTH the DLL which implements polymorphic_derived2
// as well as the main program.
BOOST_CLASS_EXPORT_KEY(PlugInClass_Derived_1::Parameter)

// note the mixing of type_info systems is supported.
BOOST_CLASS_TYPE_INFO(
PlugInClass_Derived_1::Parameter,
boost::serialization::extended_type_info_typeid<PlugInClass_Derived_1::Parameter>
)

//PlugInClass_Derived_1.cpp

/* boost headers go here */

/* plugin headers go here */
#define POLYMORPHIC_DERIVED2_EXPORT
#include "PlugInClass_Derived_1.h"

PlugInClass_Derived_1::Parameter::Parameter():
a(1),
b(2),
c(3)
{
d = -1.;
/*nothing*/
}

template <typename Archive>
void PlugInClass_Derived_1::Parameter::serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<PlugInClass_Base::Parameter>(*this);
ar & a;
ar & b;
ar & c;

}

boost::shared_ptr<PlugInClass_Base::Parameter> PlugInClass_Derived_1::getInitParameter(){
// get local data pointer;
boost::shared_ptr<PlugInClass_Base::Parameter> localParameter(new PlugInClass_Derived_1::Parameter());
// update parent information

// return local data
return localParameter;
}


// instantiate code for text archives
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

template EXPORT_DECL(void) PlugInClass_Derived_1::Parameter::serialize(
boost::archive::text_oarchive & ar,
const unsigned int version
);
template EXPORT_DECL(void) PlugInClass_Derived_1::Parameter::serialize(
boost::archive::text_iarchive & ar,
const unsigned int version
);

// instantiate code for polymorphic archives
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>

template EXPORT_DECL(void) PlugInClass_Derived_1::Parameter::serialize(
boost::archive::polymorphic_oarchive & ar,
const unsigned int version
);
template EXPORT_DECL(void) PlugInClass_Derived_1::Parameter::serialize(
boost::archive::polymorphic_iarchive & ar,
const unsigned int version
);


// MWerks users can do this to make their code work
BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(
PlugInClass_Base::Parameter
, PlugInClass_Derived_1::Parameter)

// note: export has to be AFTER #includes for all archive classes
BOOST_CLASS_EXPORT_IMPLEMENT(PlugInClass_Derived_1::Parameter)

//PlugInClass_Base.h

#pragma once

#ifdef PLUGIN
// All functions in this file are exported
#else
// All functions in this file are imported
#define PLUGIN __declspec(dllimport)
#endif

// boost headers
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/type_info_implementation.hpp>
#include <boost/serialization/extended_type_info_no_rtti.hpp>
#include <boost/serialization/extended_type_info_typeid.hpp>

#include <boost/preprocessor/empty.hpp>

// export_decl, import_decl from http://www.boost.org/doc/libs/1_55_0/libs/serialization/test/
#ifdef BOOST_HAS_DECLSPEC // defined in config system
#if ! defined(EXPORT_DECL)
#if defined(__BORLANDC__)
#define EXPORT_DECL(T) T __export
#else
#define EXPORT_DECL(T) __declspec(dllexport) T
#endif
#endif
#if ! defined(IMPORT_DECL)
#if defined(__BORLANDC__)
#define IMPORT_DECL(T) T __import
#else
#define IMPORT_DECL(T) __declspec(dllimport) T
#endif
#endif
#else
#define IMPORT_DECL(T) T
#define EXPORT_DECL(T) T
#endif // BOOST_HAS_DECLSPEC

#if defined(POLYMORPHIC_DERIVED_IMPORT)
#define DLL_DECL IMPORT_DECL
#elif defined(POLYMORPHIC_DERIVED_EXPORT)
#define DLL_DECL EXPORT_DECL
#else
#define DLL_DECL(x)
#endif

class PlugInClass_Base
{
public:

class DLL_DECL(BOOST_PP_EMPTY()) Parameter
{
public:

double d;

virtual ~Parameter(void){};

private:
friend class boost::serialization::access;

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

public:
virtual const char * get_key() const = 0;
};

public:

/** @brief standard constructor */
PlugInClass_Base(){};
virtual ~PlugInClass_Base(){};

PLUGIN virtual boost::shared_ptr<PlugInClass_Base::Parameter> getInitParameter(){return NULL;};
};

BOOST_SERIALIZATION_ASSUME_ABSTRACT(PlugInClass_Base::Parameter)

// we use this because we want to assign a key to this type
// but we don't want to explicitly instantiate code every time
// we do so!!!. If we don't do this, we end up with the same
// code in BOTH the DLL which implements polymorphic_derived2
// as well as the main program.
BOOST_CLASS_EXPORT_KEY(PlugInClass_Base::Parameter)

// note the mixing of type_info systems is supported.
BOOST_CLASS_TYPE_INFO(
PlugInClass_Base::Parameter,
boost::serialization::extended_type_info_typeid<PlugInClass_Base::Parameter>
)

///######### dll 结束 ###################///

//至少是主要的

#include <stdio.h>
#include <tchar.h>
#include <fstream>
#include <sstream>

#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/type_info_implementation.hpp>
#include <boost/serialization/extended_type_info_no_rtti.hpp>

#include "PlugIn_Derived\PlugInClass_Base.h"

#include <windows.h>
int main(int argc, char** argv)
{

boost::shared_ptr<PlugInClass_Base> dll_;

/// ######### load dll ################### ///
std::string pluginPath_ = "PlugInClass_Derived_2.dll";

HINSTANCE currLibrary = LoadLibrary(pluginPath_.c_str());

if (!currLibrary) {
throw std::runtime_error("The plugin could not be loaded.");
}

// load the plugin class interface from the library using its factory functions
typedef PlugInClass_Base *(*CreatePluginFuncDef)();
CreatePluginFuncDef pluginCreateFactoryPtr = (CreatePluginFuncDef)GetProcAddress(currLibrary, "Create");
typedef void(*DestroyPluginFuncDef)(PlugInClass_Base*);
DestroyPluginFuncDef pluginDestroyPtr = (DestroyPluginFuncDef)GetProcAddress(currLibrary, "Destroy");
// create object within dll
dll_ = boost::shared_ptr<PlugInClass_Base>(pluginCreateFactoryPtr(), pluginDestroyPtr);

/// ######### get object from dll ################### ///
boost::shared_ptr<PlugInClass_Base::Parameter> parameterPtr = dll_->getInitParameter();

/// ######### serialization ################### ///
std::string s;
// create and open a character archive for output
{
std::ostringstream os;
// save data to archive
boost::archive::text_oarchive oa(os);

// write class instance to archive
oa << parameterPtr; // HERE RUNTIME ERROR
// Unhandled exception at xxxx in test_dll_simple_example.exe:
// Microsoft C++ exception: boost::archive::archive_exception at memory location xxxx

s = os.str();
}

// ... some time later restore the class instance to its orginal state

std::system("pause");
return 0;
}

如您所见,我想要的类始终是一个嵌套类“Parameter”,定义在“dll”接口(interface) (PlugInClass_Base) 的派生类中,并派生自基类的参数类(即 PlugInClass_Derived_1::Parameter)。 dll 函数“getInitParameter”返回指向我们要存储的参数类的基类的基指针。

你能看出我在连载过程中做错了什么吗?如果你能给我一些提示,我会很高兴。

亚历山德罗斯。

最佳答案

我发现,如果将基指针转换为派生指针,则序列化有效。

    /// ######### get object from dll ################### ///
boost::shared_ptr<PlugInClass_Base::Parameter> parameterPtr = dll_->getInitParameter();
boost::shared_ptr<PlugInClass_Derived_2::Parameter> derivedParameterPtr = boost::static_pointer_cast<PlugInClass_Derived_2::Parameter>(parameterPtr);

/// ######### serialization ################### ///
std::string s;
// create and open a character archive for output
{
std::ostringstream os;
// save data to archive
boost::archive::text_oarchive oa(os);

oa << derivedParameterPtr; // It works !!!

s = os.str();
}

因此,序列化无法通过基指针中的所有派生指针。基类是一个抽象类

(BOOST_SERIALIZATION_ASSUME_ABSTRACT(PlugInClass_Base::Parameter))

并且 key 被导出

BOOST_CLASS_EXPORT_KEY(PlugInClass_Base::Parameter)

并且导出每个派生类的实现(在cpp文件中)

BOOST_CLASS_EXPORT_IMPLEMENT(PlugInClass_Derived_1::Parameter)

嵌套类的键有问题吗?否则所有派生类都有自己的 get_key() 函数。

有什么假设吗?

关于c++ - 在 dll 中定义的派生嵌套类的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26218507/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com