我正在尝试将我的一个旧 C++ 程序从 ANSI 转换为 Unicode。我正在使用 Visual Studio 2022。在我对源代码进行了所有更改之后,我的程序编译时没有错误,但它没有链接,说 WinMain 是预期的,但我已经得到了 wWinMain。
LIBCMTD.lib(exe_winmain.obj):错误LNK2019:函数“int __cdecl invoke_main(void)”中引用的无法解析的外部符号_WinMain@16(?invoke_main@@YAHXZ)
我的宣言:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR cmdline, int nCmdShow)
所以我的问题是:它如何决定是调用WinMain还是wWinMain?看起来源代码是正确的,只是需要更改一些项目设置。
也许我的问题的根源在其他地方,所以我尝试添加更多信息:
该程序由一些静态库(.lib)+主exe项目组成,所有这些C++项目都位于同一个.sln解决方案中。所以我在这个解决方案中所有项目的项目配置中设置了“字符集:使用Unicode字符集”。
在我将源代码转换为使用 wchar_t 或 TCHAR 以及 Unicode 的所有相关函数后,所有 lib 项目都可以正确编译。但主项目的某些.cpp文件无法编译,编译错误显示TCHAR = char。由于TCHAR定义是基于是否定义了_UNICODE,所以我手动添加了预处理器定义_UNICODE和UNICODE。现在一切编译都没有错误。但它没有链接 - 它需要 WinMain,但我的代码中有 wWinMain。
那么,我的问题是:它如何决定是调用 WinMain 还是 wWinMain?
MSDN 说:
编译器如何知道调用 wWinMain 而不是标准的 主功能?实际发生的情况是 Microsoft C 运行时 库(CRT)提供了 main 的实现,可以调用 WinMain 或 wWinMain。
这并不能真正回答问题。编译器如何决定调用其中哪一个? 项目配置中除了“字符集:使用Unicode字符集”之外还需要设置什么?
最后,我发现问题在于我的
wWinMain
在图书馆里。正如我所提到的,我的解决方案中有一些静态库 (.lib)。所以我做了一个简单的测试应用程序来证明这一点。
我的测试程序如下所示:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
int APIENTRY _tWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPTSTR, _In_ int) { }
如果此代码位于主应用程序 (.exe) 中,则可以用 MBCS 或 Unicode 对其进行编译,没有任何问题。
_tWinMain
分别翻译为WinMain
或wWinMain
,链接成功。
但是如果我将相同的代码放入静态库(.lib)中,链接器将无法按预期工作。 MBCS 有效,这意味着它可以找到
WinMain
并调用它。它有效。但是 Unicode 大小写不起作用,链接器找不到我的 wWinMain
,然后它输出关于缺少 WinMain
的令人困惑的错误消息。
解决方案:
虽然这看起来是 Microsoft 链接器的错误或设计缺陷,但有一个简单的解决方法:我只需将库中的方法重命名为
xWinMain
并将名为 _tWinMain
的代理方法添加到主项目(.exe) )这称为我的xWinMain
。一切都在 MBCS 和 Unicode 中运行良好。
(使用 Visual Studio 2015 和 2022 中的 C++ 工具集进行测试。)