简体   繁体   中英

undefined reference to `WinMain@16' mingw converting to DLL

I am trying to convert the given C code to DLL file I tried to compile the given code but it doesn't work it gives me an error

.\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

I have already tried looking up the answers available online, along with looking at the syntax which seems to be okay.

My Code

#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;
}

I'm using Visual Studio 2017 community edition, version 15.8.1 for reference. I created a simple DLL project (using File | New | Project) and removed all files except dllmain.cpp I had to modify the project properties to disable the use of precompiled headers. The code in dllmain.cpp is:

#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;
}  

I've made a few modifications from your code,

  1. I passed MB_YESNO as the final argument to MessageBox instead of a null pointer. This will give your message box YES and NO buttons, and this matches the type expected (uint) for the fourth parameter.
  2. I used MessageBoxA to force ASCII argument instead of MessageBox, which is a typedef that resolves to MessageBoxW. This effects the type of strings that is expected, and is based on if you are using Unicode or not.
  3. I passed a value of zero for the second argument (dwStackSize) and the fifth argument (dwCreationFlags) of CreateThread instead of NULL. Both of these arguments have type DWORD. Notice that this fixes the first line of your error message ".\\sample.cpp:16:66: warning: passing NULL to non-pointer argument 5"
  4. I declared a variable dwTID and pass a pointer to it as the sixth argument of CreateThread .
  5. I added a break statement to the first case. This should not have any consequence in the code. I just think it is a good idea.

The above code compiles without warnings or errors. Thus I believe that your code should also compile as well. Thus I strongly suspect that the errors you are seeing are due to the compiler and linker flags you are using. The command lines that are being used are

for compilation:

/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 

for linking:

/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 

Because you are not using native Microsoft toos (CL and LINK), you are going to need to find or prepare a mapping between the tool chain you are using (which you did not mention, but it appears to be mingw from the error messages) and Microsoft's tool chain.

If'n I had to guess, I would suspect that the issue is due to the /DLL flag in the linking command line. You might have to use something line -shared with mingw. However this is just a guess.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM