GetProcAddress возвращает NULL

Мне нужно использовать простую функцию из 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;
...

person gc5    schedule 12.08.2011    source источник


Ответы (1)


Да, вызов MessageBox() прошел без ошибок. Переместите вызов GetLastError() перед ним.

В противном случае ошибка предсказуема, она не смогла найти «mouseProc». Имя будет искажено в DLL, скорее всего "_mouseProc@12". Используйте dumpbin.exe /exports в своей DLL, чтобы быть уверенным.

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

person Hans Passant    schedule 12.08.2011
comment
Да, это так :) Имя процедуры точно _mouseProc@12. Я думал, что использование extern "C" позволит избежать искажения имени в функции. Есть ли способ сделать это или мне нужно использовать _mouseProc@12? - person gc5; 13.08.2011
comment
Вы можете добавить файл определений компоновщика (.DEF), чтобы изменить имя на любое другое. - person hamstergene; 13.08.2011
comment
@Francesco - это имя искаженное имя C, а не искаженное имя C++. Искаженные имена C++ должны справляться с перегрузкой, поэтому они описывают (зашифрованным образом) типы всех параметров. Начальное подчеркивание почти всегда добавлялось к именам функций C в объектных файлах - я не знаю, почему. Я не знаю, что представляет собой @12 — может быть, кто-то другой знает? В любом случае, в наши дни полностью неукрашенные имена в объектном или целевом файле встречаются очень редко — это просто неприятность, к которой мы все должны привыкнуть. - person Steve314; 13.08.2011
comment
Такое искажение решает проблему в 32-битном коде. У которого есть много разных соглашений о вызовах, __cdecl, __stdcall и __fastcall являются более распространенными. Получение несоответствия приводит к тому, что очень трудно диагностировать ошибки времени выполнения. Оформляя функцию таким образом, компоновщик может обнаружить такое несоответствие. Вы использовали __stdcall, постфикс @xx указывает размер кадра стека активации. Три аргумента, каждый по 4 байта. Не исправляйте это, вместо этого используйте технику из последнего абзаца моего ответа. - person Hans Passant; 13.08.2011