返回

Unicode Windows 应用程序创建的例外行为:WinMain 函数无法解析

windows

Unicode Windows 应用程序创建的例外行为

在构建 Windows 应用程序时,我们经常将启动代码放入库中,以便应用程序无需处理这些代码。这些库通常包含一个 wWinMain 函数,在 Visual Studio 中作为 Unicode 项目构建。

问题

当您将上述库与 Unicode 应用程序链接时,您可能会收到未解析的外部符号错误:

MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)

即使您在库中包含了 wWinMain 函数,也会发生这种情况。

原因

这是因为 Visual Studio 默认情况下使用 CRT(C 运行时库)的动态链接版本。当应用程序的入口点是 Unicode wWinMain 时,CRT 的静态版本需要被链接。

解决方案

要解决此问题,您可以执行以下操作:

  1. 将库的运行时库选项更改为多线程静态 DLL (MTd): 在库的链接器设置中,将“运行时库”选项从“多线程 DLL (MD)”更改为“多线程静态 DLL (MTd)”。
  2. 使用 wWinMainCRTStartup 作为入口点: 在库中,将 wWinMain 函数重命名为 wWinMainCRTStartup。这将指示链接器使用 CRT 的静态版本。
  3. 显式指定入口点: 在应用程序的可执行文件中,显式将入口点指定为 wWinMain,如下所示:
#pragma comment(linker, "/ENTRY:wWinMain")

其他注意事项

  • 如果您正在使用 Visual Studio 2017 或更早版本,您需要将应用程序的“字符集”选项设置为“使用 Unicode 字符集”。
  • 如果您正在使用 Visual Studio 2019 或更高版本,您可以省略此步骤,因为默认情况下会启用 Unicode。

结论

将 WinMain 函数的 Unicode 版本放入外部库时,由于 Visual Studio 的默认 CRT 设置,您可能会遇到问题。通过遵循本文中的解决方案,您可以解决未解析的外部符号错误并创建正确的 Unicode Windows 应用程序。

常见问题解答

  1. 为什么使用 CRT 的静态版本很重要?

    • 当使用动态链接时,应用程序会依赖于操作系统提供的 CRT 版本。使用静态版本确保应用程序包含其自己的 CRT 副本,消除依赖关系。
  2. 为什么 wWinMainCRTStartup 可以解决问题?

    • wWinMainCRTStartup 是 wWinMain 函数的特殊版本,显式指示链接器使用 CRT 的静态版本。
  3. 为什么需要显式指定入口点?

    • 在某些情况下,链接器可能无法自动检测 wWinMain 函数。显式指定入口点确保链接器正确链接应用程序。
  4. 如何检查正在使用的 CRT 版本?

    • 可以在应用程序的“属性”页面的“链接器”>“输入”选项卡中找到正在使用的 CRT 版本。
  5. 是否有其他方法可以解决此问题?

    • 是的,您还可以使用生成脚本或第三方构建工具来配置 CRT 选项和入口点。