Переменная становится равной NULL после функции в DLL - PullRequest
0 голосов
/ 29 июня 2011

Мне нужны действительные данные в глобальной переменной 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.

РЕДАКТИРОВАТЬ: Здесь я выполняю install ()

    // 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 ]

1 голос
/ 29 июня 2011

Ваш звонок на install действительно происходит в адресном пространстве dll (в отладчике войдите в вызов и проверьте адреса в стеке вызовов)? install определен в заголовочном файле или это извлечение из исходного файла? Если в заголовке, он встроен в ваш exe, так что dll-версия p никогда не устанавливается. Это может произойти без предупреждения компоновщика, поскольку существуют два независимых двоичных файла, использующих один и тот же источник.

Определено ли MOUSEHOOKSHARED_EXPORT в вашем приложении? Вероятно, должно быть MOUSEHOOKSHARED_IMPORT для приложения (но не DLL).

1 голос
/ 29 июня 2011

Вы экспортируете глобал в DLL, а затем импортируете его в программу?Если вы этого не делаете или делаете неправильно, у вас, вероятно, есть два объекта p: один в DLL и один в программе.Вы можете подтвердить это, проверив адрес p.

Вместо того, чтобы использовать глобальную переменную, рассмотрите возможность использования экспортированной функции в DLL, которая возвращает необходимую ссылку / указатель.По крайней мере, назовите это что-то более наглядное (если только оно не было переименовано для того, чтобы задать этот вопрос).

0 голосов
/ 29 июня 2011

Вы создаете поверхностную копию этого параметра mParent. В какой-то момент этот указатель должен получить значение null (или вы передаете его как null), что приведет к тому, что p также станет null.

...