0

グローバル変数に有効なデータが必要です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は、であるため、自身をに初期化します。したがって、になります。ただし、完全に異なるメモリアドレスで戻ると、スコープに戻ります。広範囲にわたるデバッグと頭痛の種の後の解決策は、パラメーターとしてを取り、それをの代わりにに渡すクラスメンバー関数を作成することです。その関数に渡すものはすべて、DLLが持続する必要がある限り持続する必要があります。または、ディープコピーを実行する独自のコピーコンストラクターを作成できます。installmParentQObjectNULLpNULLthisinstallQObjectinstallthis

4

3 に答える 3

1

installdllアドレス空間で実際に発生している呼び出しですか(デバッガーで、呼び出しにステップインし、コールスタック内のアドレスを確認します)?ヘッダーファイルで定義されていinstallますか、それともソースファイルから抽出されていますか?ヘッダーにある場合は、exeにインライン化されているため、dllバージョンのpが設定されることはありません。同じソースを使用する2つの独立したバイナリがあるため、これはリンカーの警告なしに発生します。

MOUSEHOOKSHARED_EXPORTアプリで定義されていますか?おそらくアプリ用である必要がありますMOUSEHOOKSHARED_IMPORT(dllではありません)。

于 2011-06-29T17:30:11.980 に答える
1

DLLでグローバルをエクスポートしてから、プログラムにインポートしていますか?そうでない場合、または正しく実行していない場合は、おそらく2つのpオブジェクトがあります。1つはDLLにあり、もう1つはプログラムにあります。のアドレスを確認することで確認できますp

グローバル変数ではなく、必要な参照/ポインターを返すDLLでエクスポートされた関数を使用することを検討してください。少なくとも、よりわかりやすい名前を付けてください(この質問をするために名前が変更された場合を除きます)。

于 2011-06-29T17:59:26.563 に答える
0

そのパラメータmParentの浅いコピーを作成しています。ある時点で、そのポインタはnullに設定されている必要があります(またはnullとして渡されます)。これにより、pもnullになります。

于 2011-06-29T17:29:20.030 に答える