我正在尝试从 DLL 中获取类静态数据成员的地址并将其保存在主机代码中。但是,当我退出打开所有(Windows typedef)HINSTANCE的 dll 管理器中的方法时,我丢失了对成员的指针/引用,即使我让它们保持打开状态。
我的设置是:
一个 Qt GUI 应用程序,它包括一个从 dll 加载插件的类。这个 dll-manager 类不使用 Qt 的东西,而是用于 Qdir 和 Qstrings 这里和那里......
dll 管理器应该发出一堆 LoadLibrary() 调用来打开 DLL,并为每个调用调用一个导出函数,该函数返回 DLL 导出的类中的静态“信息”结构的地址。
例如,DLL 类如下所示:
BlackNWhite.h
#ifdef BLACKNWHITE_EXPORTS
#define BLACKNWHITE_API __declspec(dllexport)
#else
#define BLACKNWHITE_API __declspec(dllimport)
#endif
// This class is exported from the BlackNWhite.dll
class BLACKNWHITE_API CBlackNWhite : PCOperatorBase
{
public:
CBlackNWhite(void);
virtual ~CBlackNWhite(void);
virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
void getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters);
static const OperatorInfo& info();
protected:
static OperatorInfo operatorInfo;
};
extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance();
extern "C" __declspec(dllexport) const PCOperatorBase::OperatorInfo& getOperatorInfo();
BlackNWhite.cpp
#include "stdafx.h"
#include "BlackNWhite.h"
PCOperatorBase::OperatorInfo CBlackNWhite::operatorInfo = {L"Black N White", L"modifier", L"color"};
const PCOperatorBase::OperatorInfo& CBlackNWhite::info()
{
return CBlackNWhite::operatorInfo;
}
extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance()
{
return (PCOperatorBase*)(new CBlackNWhite());
}
extern "C" __declspec(dllexport) const PCOperatorBase::OperatorInfo& getOperatorInfo()
{
return CBlackNWhite::info();
}
CBlackNWhite::CBlackNWhite()
: PCOperatorBase()
{
ParameterDescriptor newParameter;
newParameter.label = L"Parameter 1";
parameters.push_back(newParameter);
}
CBlackNWhite::~CBlackNWhite()
{
}
int CBlackNWhite::process(int* inBuffer, int* outBuffer, int bufferSize)
{
while(bufferSize--)
*outBuffer++ = *inBuffer++;
return 0;
}
void CBlackNWhite::getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters)
{
outParameters = ¶meters;
}
这个类继承自一个基类:
PCOperatorBase.h
#pragma once
#include "PCOperatorParameters.h"
#include <vector>
class PCOperatorBase
{
public:
typedef struct OperatorInfo
{
wchar_t* name;
wchar_t* type;
wchar_t* subtype;
} OperatorInfo;
PCOperatorBase(void){};
virtual ~PCOperatorBase(void){};
virtual void getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters) = 0;
virtual int process(int* inBuffer, int* outBuffer, int bufferSize) = 0;
protected:
std::vector<ParameterDescriptor>parameters;
};
并且 DLL-manager 有两个相关的方法。一个构建可用插件的列表,另一个只返回插件的字符串名称。
void PCOperatorManager::buildOperatorList(const QString path)
{
QDir operatorDirectory(QDir::currentPath() + path);
if(operatorList.size())
operatorList.clear();
QStringList operatorNameList = operatorDirectory.entryList(QStringList("*.dll"));
typedef PCOperatorBase::OperatorInfo*(*PCOClassInfoFunction)();
for(QStringList::iterator PCOClassName = operatorNameList.begin();
PCOClassName != operatorNameList.end();
PCOClassName++)
{
HINSTANCE PCOClassHandle;
if((PCOClassHandle = LoadLibrary((operatorDirectory.absolutePath() + "/"+ *PCOClassName).toStdWString().c_str())))
{
OperatorDescriptor newPCOClassDescriptor;
newPCOClassDescriptor.handle = PCOClassHandle;
newPCOClassDescriptor.info = (*((PCOClassInfoFunction)GetProcAddress(PCOClassHandle, "getOperatorInfo")))();
operatorList.push_back(newPCOClassDescriptor);
printf("\n we have: %ls", operatorList[0].info->name);
}
}
}
QStringList PCOperatorManager::getOperatorNameList()
{
QStringList operatorNameList;
printf("\n the list length is: %i", operatorList.size());
for(int i = 0; i < operatorList.size(); i++)
printf("\n we have again: %ls", operatorList[0].info->name);
//operatorNameList << QString::fromWCharArray((*PCOClass).info.name);
return operatorNameList;
}
发生的事情是:在 buildOperatorList() 中,我可以访问 DLL 类的静态成员并将其分配给 OperatorDescriptor 结构中的 info 成员。也就是说,读取“我们拥有”的“测试”printf 语句确实打印出该字段的正确值。
但是,在getOperatorNameList()
info 成员内部不再有效。
我的思路是,我正在做的是:
- 我有一个指向 OperatorInfo 结构的指针,称为 info。
- 我得到了 DLL 类中的静态 OperatorInfo 结构的地址,称为 operatorInfo。
- 我将类的 operatorInfo 的地址分配给名为 info 的指针。那是
info = &CBlackNWhite::operatorInfo;
此时,只要我不在 DLL HINSTANCE上发出 FreeLibrary(),指针就应该保持有效
发生什么了?