неопределенная ссылка на mingw `WinMain @ 16 ', преобразующий в DLL - PullRequest
0 голосов
/ 07 июля 2019

Я пытаюсь преобразовать данный код C в файл DLL. Я пытался скомпилировать данный код, но он не работает, он выдает ошибку

.\sample.cpp:16:66: warning: passing NULL to non-pointer argument 5 of 'void* CreateThread(LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, PVOID, DWORD, PDWORD)' [-Wconversion-null]
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../libmingw32.a(main.o):(.text.startup+0xb0): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status

Я уже пытался найти доступные ответы в Интернете, а также посмотреть на синтаксис, который кажется нормальным.

Мой код

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

extern "C" __declspec(dllexport)
DWORD WINAPI MessageBoxThread(LPVOID lpParam) {
  MessageBox(NULL, "Hello world!", "Hello World!", NULL);
  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, MessageBoxThread, NULL, NULL, NULL);
      break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
      break;
  }
  return TRUE;
}

1 Ответ

0 голосов
/ 07 июля 2019

Я пользуюсь Visual Studio 2017 Community Edition версии 15.8.1 для справки.Я создал простой проект DLL (используя File | New | Project) и удалил все файлы, кроме dllmain.cpp. Мне пришлось изменить свойства проекта, чтобы отключить использование предварительно скомпилированных заголовков.Код в dllmain.cpp:

#define WIN32_LEAN_AND_MEAN   
#include <windows.h>

extern "C" __declspec(dllexport)
DWORD WINAPI MessageBoxThread(LPVOID lpParam)
{
    MessageBoxA(NULL, "Hello World", "Hello World", MB_YESNO);
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
            DWORD   dwTID;
            CreateThread(nullptr, 0, MessageBoxThread, nullptr, 0, &dwTID);
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}  

Я сделал несколько изменений в вашем коде,

  1. Я передал MB_YESNO в качестве последнего аргумента MessageBox вместонулевой указатель.Это даст вашему окну сообщения кнопки ДА и НЕТ, и это соответствует ожидаемому типу (uint) для четвертого параметра.
  2. Я использовал MessageBoxA для принудительного вызова аргумента ASCII вместо MessageBox, который является typedef, который разрешается в MessageBoxW,Это влияет на ожидаемый тип строк и основывается на том, используете ли вы Юникод или нет.
  3. Я передал нулевое значение для второго аргумента (dwStackSize) и пятого аргумента (dwCreationFlags) CreateThread вместо NULL.Оба эти аргумента имеют тип DWORD.Обратите внимание, что это исправляет первую строку вашего сообщения об ошибке ". \ Sample.cpp: 16: 66: warning: передача NULL аргументу без указателя 5"
  4. Я объявил переменную dwTID и передал указательк нему в качестве шестого аргумента CreateThread.
  5. я добавил оператор break в первый случай.Это не должно иметь никаких последствий в коде.Я просто думаю, что это хорошая идея.

Приведенный выше код компилируется без предупреждений или ошибок.Таким образом, я считаю, что ваш код также должен компилироваться.Поэтому я сильно подозреваю, что ошибки, которые вы видите, происходят из-за используемых вами флагов компилятора и компоновщика.Используются следующие командные строки:

для компиляции:

/JMC /permissive- /GS /analyze- /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"Debug\vc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "TESTDLL_EXPORTS" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /FC /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\testDll.pch" /diagnostics:classic 

для компоновки:

/OUT:"D:\GNUHome\Projects\testDll\Debug\testDll.dll" /MANIFEST /NXCOMPAT /PDB:"D:\GNUHome\Projects\testDll\Debug\testDll.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib"/IMPLIB:"D:\GNUHome\Projects\testDll\Debug\testDll.lib" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"D:\GNUHome\Projects\testDll\Debug\testDll.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\testDll.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 

Поскольку вы не используете нативные задачи Microsoft (CL и LINK) вам нужно будет найти или подготовить сопоставление между цепочкой инструментов, которую вы используете (которую вы не упомянули, но, похоже, она совпадает с сообщениями об ошибках), и цепочкой инструментов Microsoft.

ЕслиИ я должен был догадаться, я подозреваю, что проблема связана с флагом /DLL в командной строке связывания.Возможно, вам придется использовать строку -shared с Mingw.Однако это только предположение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...