我有一个dll(“so.dll”)定义如下,其中我有一个函数TestWrongClass,它返回一个指针 到一个类对象(TestWrongClass)。
/////// "IOReader.h" //////////////
class IOReader
{
public :
IOReader() {};
virtual ~IOReader() {};
virtual bool open(const std::string &format,
const std::string &fileName, const int mask) = 0;
std::string errorMessage;
};
// "IOReader.h" Ends Here
// ---- so.dll ---- /
//////////////// sio.h ////////////
#ifdef SEIO_EXPORTS
#define SEIO_API __declspec(dllexport)
#else
#define SEIO_API __declspec(dllimport)
#endif
#include <string>
#include "IOReader.h"
class SReaderIO : public IOReader
{
public:
SReaderIO() {};
bool open(const std::string &format,
const std::string &fileName, const int mask)
{
return true;
}
};
class TestWrongClass
{
public:
TestWrongClass() { };
bool open(const std::string &format,
const std::string &fileName, const int mask)
{
return true;
}
};
SEIO_API TestWrongClass* CreateIOReader()
{
TestWrongClass * module = new TestWrongClass();
return module;
}
//// sio.h ends here ///////
//in the main executable I am loading the dll on run time
// and after creating a object of type TestWrongClass,
//I explicitly try to cast it with the wrong object, as follows
/// Main Source //
#include <iostream>
#include <windows.h>
#include "IOReader.h"
int main ()
{
HMODULE hDLL=LoadLibrary(L"sIO.dll");
CreateSealafineReaderFn _funcSelafinCreator = NULL;
_funcSelafinCreator = (CreateSealafineReaderFn) GetProcAddress (hDLL,
"CreateIOReader");
// Method 1
void *Iref = (_funcSelafinCreator)();
IOReader * locReader = NULL;
locReader = reinterpret_cast <IOReader *>(Iref); // but how to check
// that object locReader is not of base type IOReader
// so that I may call delete Iref
// If I try to do as follow, then I get illegal error from compiler
// locReader = dynamic_cast <IOReader *>(Iref); // illegal
// Method 2
try
{
locReader = dynamic_cast <IOReader *>((_funcSelafinCreator)());
// works but how can I check wrong casting and catch exception
} catch (std::bast_cast)
{
// how to clear the object created by CreateIOReader
}
}
//
我执行此过程的原因是检查是否有任何dll,主程序将从dll目录扫描 可能具有相同名称的方法,但是该方法所创建的对象的返回指针类型可能不同,这是不希望的。 (在上面提到的情况下,方法是CreateIOReader)
如果我使用dynamic_cast,我可以检查bad_cast异常,但是对象将在dll中创建,并且不会被释放,因为我 无法访问dll的内部代码。
我使用reintepret_cast给出的上述方法有效,但我无法检查是否返回了正确的对象类型。 如果通过某种方法了解如果转换的类型不正确,那么我可以在Iref指针“delete Iref”上调用delete来清除堆中的对象。
是否有任何方法可以通过CreateIOReader方法检查错误对象的创建,从而将其从可执行源代码中删除
答案 0 :(得分:2)
对于此问题dynamic_cast
无法帮助您。问题是你不知道你的函数的实际返回类型,只是假装它是IOReader*
,而它实际上可能是其他东西(即TestWrongClass*
)。在别名规则下,这是不允许的。
将此与情况进行对比:
class IBase { ... };
class IOReader : public IBase { ... };
class TestWrongClass : public IBase { ... };
你也知道你的函数返回IBase*
。确实,动态演员可以帮助您,因为IOReader
和TestWrongClass
具有共同的祖先,并且通过IBase*
引用是有效的。
我不得不说这是一个奇怪的问题:调用库函数,你不知道可能会返回什么。我建议稍微改变一下设计。你可以(除其他外):
std::pair<int, void*>
的内容,其中int
(或enum
)是确定返回内容的可靠方式,之后您可以{{1} reinterpret_cast
如果选择方法1,然后解决删除问题,可以在void*
接口添加destroy()
之类的函数,这会导致库删除对象(注意:它是错误的想法IBase
自己由外部图书馆提供给你的对象。
如果您选择方法2,那么也许您可以拥有像delete
这样的库函数,如果您收到的不是您想要的内容,您可以传递void destroy(int, void*)
的成员。然后,库可以使用这些将std::pair
强制转换为正确的内容以在内部删除它。