Переменная становится равной NULL после функции в DLL
Мне нужны действительные данные, чтобы быть в глобальной переменной QObject *p
, Однако присвоение чего-либо этой переменной внутри функции работает в рамках функции, но после того, как функция вернется, p
возвращается в NULL, даже если p
является глобальным. Вот мой код:
#include ... // various includes
// p is NULL
QObject *p;
HHOOK hhk;
BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in DWORD fdwReason, __in LPVOID lpvReserved)
{
return TRUE;
}
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MOUSEHOOKSTRUCT *mouseInfo = (MOUSEHOOKSTRUCT*)lParam;
QMouseEvent::Type type;
QPoint pos = QPoint(mouseInfo->pt.x, mouseInfo->pt.y);
Qt::MouseButton bu;
Qt::MouseButtons bus;
Qt::KeyboardModifiers md = Qt::NoModifier;
... // very large switch statement
// here is where i need some valid data in p
QCoreApplication::postEvent(p, new QMouseEvent(type, pos, bu, bus, md));
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
// note: MOUSEHOOKSHARED_EXPORT is the same as __declspec(dllexport)
// this function is called by the application that loads the dll
extern "C" MOUSEHOOKSHARED_EXPORT void install(QObject *mParent, DWORD threadID, HINSTANCE hInst)
{
p = mParent; // p is assigned here and keeps the value of mParent untill the function returns
hhk = SetWindowsHookEx(WH_MOUSE, MouseProc, hInst, threadID);
} // after this function returns, p is NULL
extern "C" MOUSEHOOKSHARED_EXPORT void uninstall()
{
UnhookWindowsHookEx(hhk);
}
Я пробовал различные "обходные пути" структуры данных, такие как использование struct
typedef
и т.д... я не могу заставить это работать. Все, что мне нужно, это для p
сохранить ценность mParent
,
РЕДАКТИРОВАТЬ: Здесь я выполняю установку ()
// EarthWidget is a class that is derived from QWidget(which is derived from QObject)
void EarthWidget::LoadAll()
{
HINSTANCE DLLinst = LoadLibrary("MouseHook.dll");
... // get functions in DLL using GetProcAddress & typedefs, etc...
// i pass in 'this' as mParent
install(this, GetWindowThreadProcessId((HWND)earthplugin->GetRenderHwnd(), NULL), DLLinst);
// note that GetWindowThreadProcessId does work and does return a valid thread id, so no problem there
}
РЕДАКТИРОВАТЬ: выяснил, что было не так. this
указатель становится вне области видимости, когда install
выполняется, поэтому mParent
, быть QObject
, инициализируется NULL
, таким образом p
становится NULL
, this
возвращается в сферу, когда install
однако возвращается по совершенно другому адресу памяти. Решение, после обширной отладки и головной боли, было бы создать функцию-член класса, которая принимает QObject
в качестве параметра и передает это в install
вместо this
, Все, что вы передаете в эту функцию, должно длиться до тех пор, пока вам нужна DLL. Это, или, вы можете создать свой собственный конструктор копирования, который выполняет глубокое копирование.
3 ответа
Вы создаете поверхностную копию этого параметра mParent. В какой-то момент этот указатель должен получить значение null (или вы передаете его как null), что приведет к тому, что p также станет null.
Вы экспортируете глобальный файл в DLL, а затем импортируете его в программу? Если вы не делаете или не делаете это правильно, у вас, вероятно, есть два p
объекты: один в DLL и один в программе. Вы можете подтвердить это, проверив адрес p
,
Вместо того, чтобы использовать глобальную переменную, рассмотрите возможность использования экспортированной функции в DLL, которая возвращает необходимую ссылку / указатель. По крайней мере, назовите это что-то более наглядное (если только оно не было переименовано для того, чтобы задать этот вопрос).
Ваш звонок install
на самом деле происходит в адресном пространстве DLL (в отладчике, войдите в вызов и проверьте адреса в стеке вызовов)? Является install
определяется в заголовочном файле или это извлечение из исходного файла? Если в заголовке, он встроен в ваш exe-файл, поэтому dll-версия p никогда не устанавливается. Это может произойти без предупреждения компоновщика, поскольку существуют два независимых двоичных файла, использующих один и тот же источник.
Является MOUSEHOOKSHARED_EXPORT
определено в вашем приложении? Наверное, должно быть MOUSEHOOKSHARED_IMPORT
для приложения (но не dll).