【问题标题】:LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup with DLLsLNK2019:未解析的外部符号 _main 在函数 ___tmainCRTStartup 中引用,带有 DLL
【发布时间】:2014-09-23 21:14:38
【问题描述】:

这是另一个关于臭名昭著的 ___tmainCRTStartup 未解析的外部符号的线程。是的,这又是关于 SDL,但它有一个转折点,AFAICS 还没有在这里介绍。 让我先清理一些参数:

1) 我正在尝试构建一个静态链接到 SDL2.lib 的 DLL。

2) 我使用的不是 Visual Studio,而是 Visual C 和控制台(先是 cmake,然后是 nmake)。

3) 该项目完全使用 C 语言,其中没有 C++ 代码(除非 SDL2 中有 C++,但 AFAIK SDL2 完全使用 C 语言)

4) SDL2.lib 中收集的所有对象和其他对象都使用 /MT 编译,即我想静态链接到 Visual C 运行时 (libcmt.lib)。

5) 然后像这样创建 SDL2.lib:

link /nologo /lib /out:SDL2.lib file1.obj file2.obj....

6) 目标 DLL 链接如下:

link /dll /subsystem:WINDOWS /out:test.dll file1.obj file2.obj ... kernel32.lib user32.lib gdi32.lib shell32.lib ole32.lib oleaut32.lib imm32.lib winmm.lib version.lib SDL2.lib

让我感到困惑的是,上面的调用产生了以下错误:

LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup 

这怎么可能发生?我清楚地将 /dll 传递给 link.exe 那么为什么 C 运行时要寻找 main() 呢?它应该在寻找 DllMain()! DLL 中的 main() 符号根本没有任何意义,但我得到了这个令人困惑的错误!

一定是 SDL2.lib 中的某些东西导致了这个问题,但老实说,我不知道什么会迫使链接器在这里寻找 main() 入口点。我的意思是,SDL2.lib 是一个链接器库,应该完全目标中立,即应该可以将 SDL2.lib 链接到 WinMain() 可执行文件,但也应该可以链接 SDL2。 lib 针对 DllMain() 库,但在这里它似乎拒绝链接到 DLL!

有人知道这里有什么问题吗?我已经搜索了几个小时,这完全让我无法理解。

编辑:有趣的是,使用 /MD 编译所有内容时不会出现问题。它仅在使用 /MT 时发生。我真的完全不知道这可能是什么原因。

EDIT2:我也尝试使用 /DSDL_MAIN_HANDLED 编译 SDL2,但它不会使错误消失。

【问题讨论】:

  • 如果您尝试从 SDL2 创建静态库,我认为您需要使用 lib.exe 而不是 link.exe。
  • 抱歉,打错字了...我使用的是带有 /lib 选项的链接。现在已更正。我也测试过直接使用 lib.exe,但它没有任何区别。
  • SDL 有太多的手脚,这是使它在许多操作系统上可移植的必要条件。您可能正在与 src/main/windows/SDL_windows_main.c 作斗争,目的是欺骗链接器,使其相信本机 Windows 程序的入口点是 main()。当阳光普照并且你的背上有风时,这很有效。使用 /MT 编译肯定会遇到非常困难的逆风。使用项目的邮件列表,这是与 Sam Lantinga 取得联系的唯一途径。
  • 你可以尝试定义一个虚拟的 main() 看看会发生什么。 :-)
  • @HansPassant:SDL_windows_main.c 不应该是罪魁祸首,因为它默认编译成一个名为 SDL2main.lib 的小型独立链接库。因为我没有链接到这个库,所以 SDL_windows_main.c 不能真正搞砸任何事情。

标签: c winapi dll sdl


【解决方案1】:

大约四年后,我终于重新审视了这个问题,在查看了所有目标文件以查看哪个是罪魁祸首之后,我终于在src/SDL.c 中找到了错误。它的末尾有这些行:

#if defined(__WIN32__)

#if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
/* Need to include DllMain() on Watcom C for some reason.. */

BOOL APIENTRY
_DllMainCRTStartup(HANDLE hModule,
                   DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
#endif /* building DLL with Watcom C */

#endif /* __WIN32__ */ 

所以 SDL 总是定义一个 _DllMainCRTStartup 符号,这似乎混淆了链接器并导致 OP 中显示的错误。杀死上面的代码(或定义HAVE_LIBC)终于解决了问题,我可以用/MT很好地构建SDL2(虽然我仍然不知道为什么用/MD编译没有引起任何问题,因为AFAICS @987654327 @ 也将在使用 /MD 编译时定义,但在这种情况下似乎不会造成任何伤害。

问题终于解决了。

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 2011-06-18
    • 2015-02-06
    • 2014-08-28
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    相关资源
    最近更新 更多