С++ GetProcAddress не работает

У меня есть следующий код:

typedef int (WINAPI* fnEngineStart)();


int __stdcall EngineStart()
{
BOOL FreeResult = 0, RunTimeLinkSuccess = 0; //variables for later use
HMODULE LibraryHandle = 0; //Here the handle to API module/dll will be stored.
fnEngineStart fn = 0;

LibraryHandle = AfxLoadLibrary(L"FlowEngine.dll"); //get the handle of our API module
//so it will now be loaded.
if (LibraryHandle != NULL) //if the library loading was successfull..
{
    fn = (fnEngineStart)GetProcAddress(LibraryHandle,
        "fnEngineStart");
    if (RunTimeLinkSuccess = (fn != NULL)) //if operation was successful...
    {
        int ReturnValue = fn(); //call messageboxa function
        //from user32.dll
    }
    else
    {
        MessageBox(0, L"Error", 0, 0);
    }
    FreeResult = FreeLibrary(LibraryHandle);
    //from this process...
    return FreeResult; //routine was successful
}
return EXIT_FAILURE; //else, it failed
}

Этот код отлично работает, например, user32.dll и MessageBoxA, но не моя собственная dll...

int __declspec(dllexport) __stdcall fnEngineStart()
{
   MessageBox(0, L"Succes!", 0, 0);
   return 0;
}

Как мне заставить это работать и для моей собственной dll? Заранее спасибо.


person VirtualCoder    schedule 05.02.2016    source источник
comment
GetProcAddress устанавливает значение для GetLastError...   -  person Alex K.    schedule 05.02.2016
comment
И этот код ошибки будет 127. Потому что имя функции украшено. Потенциально с исправлением C++, но, безусловно, украшением stdcall. Либо используйте файл .def, либо, что лучше, пусть имя будет искажено, и импортируйте его, используя искаженное имя.   -  person David Heffernan    schedule 05.02.2016


Ответы (1)


Вы столкнулись с проблемой искажения имени. Используйте extern "C", чтобы компилятор не искажал имя. Пример:

extern "C" int __declspec(dllexport) __stdcall fnEngineStart()
{
   MessageBox(0, L"Succes!", 0, 0);
   return 0;
}

Примечание. __stdcall функции украшаются символом подчеркивания в начале, за которым следует символ @, а затем количество (в байтах) аргументов, переданных в стек. Это число всегда будет кратно 4 на 32-битной машине. Источник

Если ваш компилятор поддерживает это, вы можете сделать это в своей dll, и все должно работать так, как у вас сейчас.

extern "C" int __declspec(dllexport) __stdcall fnEngineStart()
{
   #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
   MessageBox(0, L"Succes!", 0, 0);
   return 0;
}
person Alex    schedule 05.02.2016
comment
Это еще не все. Функция будет экспортирована в виде _fnEngineStart@0. Вам нужно будет использовать файл .def или переключиться на cdecl, чтобы избежать этого украшения. Или просто импортируйте функцию с ее правильным именем. - person David Heffernan; 05.02.2016