Всем привет! К сожалению, не являюсь специалистом по данной теме, решения в открытых источниках не нашлось, поэтому прошу помощи. Предполагаю, что допускаю нелепую ошибку новичка, поэтому заранее извиняюсь за возможно глупый вопрос. Есть следующий код DLL: Код (C++): BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } extern "C" __declspec(dllexport) void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { // ... } Сборка в Visual Studio, с x64 все в порядке, у x86 возникает ошибка - "Нет точки входа EntryPoint". Причем картина идентичная с rundll32.exe в SysWOW64 и System32. Windows 64-bit. В чем может быть проблема?
Как раз так и делаю, x64 сборка запускается исправно, у x86 сборки по какой-то причине не находится точка входа. --- Сообщение объединено, 26 ноя 2024 --- Возможно дело в соглашении о вызовых и для 32-bit нужно как-то переписать dllexport? --- Сообщение объединено, 26 ноя 2024 --- Да, действительно. Следующий код решает проблему: Код (Text): extern "C" __declspec(dllexport) void __cdecl Ent(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { // ... } --- Сообщение объединено, 26 ноя 2024 --- Код (C++): // Calling Convention #ifdef _WIN64 #define CALLBACK __stdcall #else #define CALLBACK __cdecl #endif extern "C" __declspec(dllexport) void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { // ... }
Потому, что под x86 будет не EntryPoint, а _EntryPoint, возьми любой PE просмотрщик типа PEAnatomist и посмотри таблицу экспорта.
EntryPoint по соглашению должен быть __stdcall. Проблема в том, что на x32 компилятор при экспорте функций с соглашениями, отличными от cdecl, добавляет твоей функции декорирование с количеством байт на стеке под аргументы. В итоге твоя функция экспортируется не как "EntryPoint", а как "_EntryPoint@16", поэтому rundll32 её не видит. Чтобы экспортировать именно под тем именем, которое ты выбрал, требуется создать def-файл с описаниями экспортируемых функций. Создай в папке с проектом файл с расширением ".def" - например, Exports.def с таким содержимым: Код (Text): EXPORTS EntryPoint Затем зайди в свойства проекта твоей библиотеки в раздел линкера и найди опцию, задающую путь к def-файлу: После этого пересобери библиотеку, и экспорт теперь будет правильным: