0

我需要有效数据在全局变量QObject *p中。但是,在函数内部为该变量分配任何东西都在函数的范围内起作用,但是在函数返回后p,即使p是全局的,也会被设置回 NULL。这是我的代码:

    #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,作为 a QObject,将自身初始化为NULL。从而p变成NULL。但是,返回时会在完全不同的内存地址处返回this范围。install经过大量调试和头疼之后,解决方案是创建一个类成员函数,该函数将 aQObject作为参数并将其传递给install而不是this. 只要您需要 DLL 持续存在,您传递给该函数的任何内容都必须持续存在。那,或者,您可以创建自己的复制构造函数来执行深度复制。

4

3 回答 3

1

您的调用是否install实际发生在 dll 地址空间中(在调试器中,进入调用并检查调用堆栈中的地址)?是install在头文件中定义还是从源文件中提取?如果在标题中,它已被内联到您的 exe 中,因此永远不会设置 p 的 dll 版本。这将在没有任何链接器警告的情况下发生,因为有两个独立的二进制文件使用相同的源。

MOUSEHOOKSHARED_EXPORT在您的应用程序中定义的吗?可能需要MOUSEHOOKSHARED_IMPORT用于应用程序(但不是 dll)。

于 2011-06-29T17:30:11.980 回答
1

您是在 DLL 中导出全局,然后在程序中导入它吗?如果不是,或者没有正确执行,您可能有两个p对象:一个在 DLL 中,一个在程序中。您可以通过查看 的地址来确认这一点p

考虑在 DLL 中使用返回所需引用/指针的导出函数,而不是全局变量。至少将它命名为更具描述性的名称(除非它只是为了提出这个问题而重命名)。

于 2011-06-29T17:59:26.563 回答
0

您正在创建该参数 mParent 的浅表副本。在某些时候,该指针必须设置为 null(或者您将其作为 null 传递),这将导致 p 也变为 null。

于 2011-06-29T17:29:20.030 回答