GetProcAddress返回NULL。

3

我需要使用来自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);
}

来自 main.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;
...
1个回答

6

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

否则,错误是可预测的,因为它找不到"mouseProc"。该名称将在DLL中被破坏,很可能是"_mouseProc@12"。使用dumpbin.exe /exports命令检查您的DLL以确保。

Fwiw: 通过链接其导入库而不是动态加载DLL,可以使此代码更少痛苦。 DLL将被注入到其他进程中并不意味着您也必须将其注入到自己的进程中。您所需的只是模块句柄,以便可以调用SetWindowsHookEx()。从DllMain()入口点获取它或使用GetModuleHandle()。


1
是的,过程名称确实是“_mouseProc@12”。我认为使用extern "C"可以避免函数名称混淆。有没有办法做到这一点,还是我必须使用“_mouseProc@12”? - gc5
2
您可以添加链接器定义(.DEF)文件来更改名称为任何您喜欢的名称。 - hamstergene
@Francesco - 那个名称是C的名称修饰,而不是C++的名称修饰。C++的名称修饰必须处理重载,因此它们以(加密的方式)描述所有参数的类型。在目标文件中,前导下划线几乎总是添加到C函数名中 - 我不知道为什么。我不知道@12代表什么 - 也许其他人知道?无论如何,在对象或目标文件中完全未装饰的名称现在非常罕见 - 这只是我们都必须习惯的烦恼。 - user180247
2
这种混淆解决了32位代码中的一个问题,其中有许多不同的调用约定,__cdecl、__stdcall和__fastcall是更常见的约定。出现不匹配会产生非常难以诊断的运行时错误。通过像那样装饰函数,链接器可以检测到这种不匹配。你使用了__stdcall,@xx后缀表示激活堆栈帧的大小。三个参数,每个4字节。不要修复它,改用我答案最后一段中的技术。 - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接