【问题标题】:GetProcAddress returns NULLGetProcAddress 返回 NULL
【发布时间】:2011-08-13 18:56:43
【问题描述】:

我必须使用 DLL 中的一个简单函数;我能够加载库,但 GetProcAddress 返回 NULL。我想我理解名字修饰,但也许我做错了什么。谢谢(代码如下,我会尽快添加所需的其他信息):

mydll.h

#ifdef MYDLL_EXPORTS
#define MYDLL_API extern "C" __declspec(dllexport)
#else
#define MYDLL_API extern "C" __declspec(dllimport)
#endif

MYDLL_API void testFunction(void);
MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam);

mydll.cpp

#include "stdafx.h"
#include "mydll.h"

// This is an example of an exported function.
MYDLL_API void testFunction(void)
{
MessageBox(NULL, (LPCWSTR)L"Test", (LPCWSTR)L"Test", MB_OK);
}

MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// processes the message
if(nCode >= 0)
{
    if(wParam != NULL && wParam == MK_RBUTTON)
    {
        MessageBox(NULL, (LPCWSTR)L"Captured mouse right button", (LPCWSTR)L"Test", MB_OK);
    }
}

// calls next hook in chain
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

ma​​in.cpp 中的代码

...
case WM_CREATE:
    {   
        // creates state for window
        stateClassPointer = new stateClass();
        // saves states pointer in a space reserved for user data
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) stateClassPointer);

        // now it will load DLL and set up hook procedure for mouse events

        // declares local variables
        HOOKPROC hkprcMouseProc;
        HINSTANCE hinstDLL; 
        HHOOK hhookMouseProc; 
        //FARPROC WINAPI test;
        // loads DLL
        if((hinstDLL = LoadLibrary(TEXT("C:\\Users\\Francesco\\Dropbox\\poli\\bi\\not\\pds\\sp\\wk5\\lsp5\\Debug\\mydll.dll"))) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error loading DLL", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        // saves DLL handle in the state class
        stateClassPointer->setHInstance(hinstDLL);
        // sets up hook procedure for mouse events
        if((hkprcMouseProc = (HOOKPROC)GetProcAddress(hinstDLL, "mouseProc")) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: GetProcAddress", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        if((hhookMouseProc = SetWindowsHookEx(WH_MOUSE, hkprcMouseProc, hinstDLL, 0)) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: SetWindowsHookEx", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        // saves hook handle in the state class
        stateClassPointer->setHHook(hhookMouseProc);
        /*test = GetProcAddress(hinstDLL, "testFunction");
        test();*/
    }
    break;
...

【问题讨论】:

    标签: c dll null hook getprocaddress


    【解决方案1】:

    是的,MessageBox() 调用成功且没有错误。将 GetLastError() 调用移到它之前。

    错误是可以预测的,它找不到“mouseProc”。该名称将在 DLL 中被破坏,很可能是“_mouseProc@12”。确保在您的 DLL 上使用 dumpbin.exe /exports。

    Fwiw:您可以通过不动态加载 DLL 而只是链接其导入库来减少这段代码的痛苦。 DLL 将被注入其他进程的事实并不意味着您必须将其注入您的进程。您所需要的只是模块句柄,因此您可以调用 SetWindowsHookEx()。从 DllMain() 入口点或使用 GetModuleHandle() 获取。

    【讨论】:

    • 是的 :) 过程名称正是“_mouseProc@12”。我认为使用 extern "C" 可以避免函数上的名称修改。有没有办法做到这一点,或者我必须使用“_mouseProc@12”?
    • 您可以添加链接器的定义 (.DEF) 文件以将名称更改为您喜欢的任何名称。
    • @Francesco - 该名称是 C 错位名称,而不是 C++ 错位名称。 C++ 重载名称必须应对重载,因此它们(以一种神秘的方式)描述了所有参数的类型。前导下划线几乎总是被添加到目标文件中的 C 函数名称中——我不知道为什么。我不知道@12 代表什么 - 也许其他人会这样做?无论如何,如今在对象或目标文件中完全未修饰的名称非常罕见——这只是我们都必须习惯的烦恼。
    • 这种修改解决了 32 位代码中的问题。其中有许多不同的调用约定,__cdecl、__stdcall 和 __fastcall 是更常见的。获得不匹配会导致非常难以诊断运行时错误。通过像这样装饰函数,链接器可以检测到这种不匹配。您使用了 __stdcall,@xx 后缀表示激活堆栈帧的大小。三个参数,每个 4 个字节。不要修复它,而是使用我答案最后一段中的技术。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    相关资源
    最近更新 更多