Как перекрестно скомпилировать DLL с экспортированными функциями

Я выполняю упражнение по захвату DLL и имею DLL-запись, которая работает так, как ожидалось, при компиляции в Visual Studio. По сути, когда DLL загружается, он выполняет команду оболочки и передает законную функциональность (в этом примере, функции CheckEvenOdd и PrintAMessage) в первоначально предназначенные DLL (в этом примере GetEvenOdd.dll). Рабочий код выглядит следующим образом.

#include "stdafx.h"
#include <windows.h>

#pragma comment(linker, "/export:CheckEvenOdd=GetEvenOdd.dll.original.CheckEvenOdd")
#pragma comment(linker, "/export:PrintAMessage=GetEvenOdd.dll.original.PrintAMessage")

extern "C" __declspec(dllexport)
DWORD WINAPI ExecuteCmd(LPVOID lpParam) {
    WinExec("c:\\Users\\Public\\execute.bat", 0);
    return 0;
}

extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, NULL, ExecuteCmd, NULL, NULL, NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Хотя он работает так, как планировалось при компиляции в Visual Studio (Windows), я хотел бы сгенерировать DLL в Linux (для использования в программе Windows). В Linux я могу перекрестно скомпилировать CPP файл (injector.cpp) и создать DLL с помощью этих команд;

i686-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL injector.cpp
i686-w64-mingw32-g++ -shared -o GetEvenOdd.dll injector.o -Wl,--out-implib,injector.a

Это создает DLL успешно. Однако, когда DLL загружается моим "приложением-жертвой" (выполняется в Windows), хотя функция "ExecuteCmd" выполняется, экспортируемые функции (из строки "pragma comment") недоступны. А именно, программа, которая загружает эту DLL, пытается найти экспортированные функции и не может (т.е. выполняется следующая ветвь приложения импорта DLL).

FNPTR fn = (FNPTR)GetProcAddress(hInst, "CheckEvenOdd");
if (!fn)
{
    std::cout << "\nCould not locate the function CheckEvenOdd";
    std::cout << "\n\nPress Enter to Continue...";
    getch();
    return EXIT_FAILURE;
} 

Это говорит мне, что строка "pragma comment" работает не так, как ожидалось, когда я создаю DLL в Linux.

Из некоторых чтений я понимаю, что эти "команды прагмы" специфичны для компилятора. Есть ли какие-то флаги, которые я могу дать "i686-w64-mingw32-g++" (или некоторое изменение кода, которое я могу сделать), чтобы экспортированные функции были доступны при компиляции DLL в Linux?

Ответы

Ответ 1

Pragmas специфичны для каждого компилятора, ваши прагмы будут работать в Visual C++, но не в MingW. Вместо этого вы можете использовать файл.def, который поддерживается Visual C++ и MinGW.

Вот что может выглядеть в вашем случае, что такое injector.def:

EXPORTS
    CheckEvenOdd = GetEvenOdd.dll.original.CheckEvenOdd
    PrintAMessage = GetEvenOdd.dll.original.PrintAMessage

Команда компиляции:

$ i686-w64-mingw32-g++ -o GetEvenOdd.dll --shared injector.cpp injector.def