我喜欢蓝天,也喜欢雨天。
分类: Windows平台
2013-09-27 18:24:40
windows支持两种类型的应用程序:GUI程序和CUI程序。前者是“图形用户界面”(Graphical user interface)的简称,后者是“控制台用户界面”(Console user interface)的简称。
用Microsoft Visual Studio来创建一个应用程序项目时,集成开发环境会设置各种链接器开关,使链接器将子系统的正确类型嵌入最终生成的执行体(executable,或者称为“可执行文件”)中。对于CUI程序,这个链接器开关是/SUBSYSTEM:CONSOLE,对于GUI程序,则是/SUBSYSTEM:WINDOWS.
应用程序类型和相应的入口函数
处理ANSI字符和字符串的GUI应用程序 _tWinMain (WinMain) WinMainCRTStartup
处理Unicode字符和字符串的GUI应用程序 _tWinMain (wWinMain) wWinMainCRTStartup
处理ANSI字符和字符串的CUI应用程序 _tmain (Main) mainCRTStartup
处理Unicode字符和字符串的CUI应用程序 _tmain (Wmain) wmainCRTStartup
类似地,如果指定了/SUBSYSTEM:CONSOLE链接器开关,链接器就会寻找main或wmain函数,并根据情况分别选择mainCRTStartup或wmainCRTStartup函数。同样地,如果main和wmain函数都没有找到,链接器会返回一个“unresolved external symbol(未解析的外部符号)”错误。
不过,一个鲜为人知的事实是,完全可以从自己的项目中移除/SUBSYSTEM链接器开关。一旦这样做,链接器就会自动判断应该将应用程序设为哪一个子系统。链接时,链接器会检查代码中包括4个函数中的哪一个(WinMain,wWinMain,main或wmain),并据此推算你的执行体应该是哪个子系统,以及应该在执行体中嵌入哪个C/C++启动函数。
Windows/Visual C++新手开发人员常犯的一个错误是在创建一个新项目时错误选择了项目类型。例如,开发人员可能选择创建一个新的Win32应用程序项目,但创建的入口函数是main生 成 应 用 程 序 时 , 会 报 告 一 个 链 接 器 错 误 , 因 为 Win32 应 用 程 序 项 目 会 设 置/SUBSYSTEM:WINDOWS链接器开关,但WinMain或wWinMain函数并不存在。此时,开发人员有以下4个选择。
*¨ 把main函数改为WinMain。这通常不是最佳方案,因为开发人员真正希望的可能是创建一个控制台应用程序。
*¨ 在Visual C++中创建一个新的Win32控制台应用程序项目,然后在新项目中添加现有的源代码模块。这个办法过于繁琐。它相当于一切都从头开始,而且必须删除原来的项目文件。
*¨ 在项目属性对话框中,定位到Configuration Properties(配置属性)/Linker(链接器)/System( 系 统 ) /SubSystem ( 子 系 统 ) 选 项 , 把 /SUBSYSTEM:WINDOWS 开 关 改 为/SUBSYSTEM:CONSOLE。这是最简单的解决方案,很少有人知道这个窍门。
*¨ 在项目属性对话框中,删除/SUBSYSTEM:WINDOWS开关。它能提供最大的灵活性。现在,链接器将根据源代码中实现的函数来执行正确的操作。用Visual Studio创建一个新的Win32应用程序或Win32控制台应用程序项目时,这才应该是真正的默认设定啊!