Answers:
考虑以下Windows API级别的程序:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
现在让我们使用GNU工具链(即g ++)来构建它,没有特殊的选择。这gnuc
只是我用于此的批处理文件。它仅提供使g ++更加标准的选项:
C:\ test> gnuc x.cpp C:\ test> objdump -x a.exe | findstr / i“ ^ subsystem” 子系统00000003(Windows CUI) C:\ test> _
这意味着链接器默认情况下会生成一个控制台子系统可执行文件。文件标题中的子系统值告诉Windows程序需要什么服务。在这种情况下,对于控制台系统,该程序需要一个控制台窗口。
这也使命令解释器等待程序完成。
现在,让我们使用GUI子系统构建它,这仅意味着该程序不需要控制台窗口:
C:\ test> gnuc x.cpp -mwindows C:\ test> objdump -x a.exe | findstr / i“ ^ subsystem” 子系统00000002(Windows GUI) C:\ test> _
希望到目前为止还可以,尽管该-mwindows
标志只是半文档化的。
没有该半文档化标志的构建将不得不更具体地告诉链接器一个子系统想要的值,然后通常必须明确指定一些Windows API导入库:
C:\ test> gnuc x.cpp -Wl--子系统,windows C:\ test> objdump -x a.exe | findstr / i“ ^ subsystem” 子系统00000002(Windows GUI) C:\ test> _
使用GNU工具链,效果很好。
但是Microsoft工具链(即Visual C ++)呢?
好,构建为控制台子系统可执行文件可以正常工作:
C:\ test> msvc x.cpp user32.lib 压缩文件 C:\ test> dumpbin / headers x.exe | 查找/ i“子系统” | 找到/ i“ Windows” 3个子系统(Windows CUI) C:\ test> _
但是,默认情况下,使用Microsoft的工具链作为GUI子系统进行构建时:
C:\ test> msvc x.cpp user32.lib / link / subsystem:windows 压缩文件 LIBCMT.lib(wincrt0.obj):错误LNK2019:函数___tmainCRTStartu中引用的未解析的外部符号_WinMain @ 16 p x.exe:致命错误LNK1120:1个未解决的外部组件 C:\ test> _
从技术上讲,这是因为默认情况下, Microsoft的链接器对于GUI子系统是非标准的。默认情况下,当子系统为GUI时,Microsoft的链接器将使用运行时库入口点,即开始执行计算机代码的函数,该函数winMainCRTStartup
调用Microsoft的non-standard WinMain
而不是standard main
。
不过,解决这个问题没什么大不了的。
您要做的就是告诉Microsoft的链接器要使用哪个入口点,即mainCRTStartup
哪个调用standard main
:
C:\ test> msvc x.cpp user32.lib / link / subsystem:windows / entry:mainCRTStartup 压缩文件 C:\ test> dumpbin / headers x.exe | 查找/ i“子系统” | 找到/ i“ Windows” 2个子系统(Windows GUI) C:\ test> _
没问题,但是非常乏味。而且如此神秘和隐藏,以至于大多数Windows程序员(大多只使用Microsoft的默认非标准工具)甚至都不知道它,并错误地认为Windows GUI子系统程序“必须”具有非标准WinMain
而非标准main
。顺便说一句,对于C ++ 0x,Microsoft会遇到问题,因为编译器随后必须宣传它是独立式的还是托管的(托管时,它必须支持standard main
)。
无论如何,这就是g ++ 可能抱怨WinMain
缺失的原因:这是Microsoft工具默认情况下对GUI子系统程序所要求的一种愚蠢的非标准启动功能。
但是正如您在上面看到的,main
即使对于GUI子系统程序,g ++在标准方面也没有问题。
那么可能是什么问题呢?
好吧,您可能缺少了main
。而且您可能也没有(适当)WinMain
!然后,在搜索main
(没有)和Microsoft的非标准(没有)之后,g ++ WinMain
报告缺少后者。
使用空源进行测试:
C:\ test>输入nul> y.cpp C:\ test> gnuc y.cpp -mwindows c:/程序文件/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2 ):未定义的参考 ce到`WinMain @ 16' collect2:ld返回1退出状态 C:\ test> _
main
或一个WinMain
,或确保相关文件包含在项目中。干杯,
main
或是winmain
什么意思?谢谢
总结以上由Cheers和hth发表的文章。-阿尔夫,请确保您有main()
或WinMain()
定义和g ++应该做正确的事情。
我的问题是main()
偶然在名称空间中定义的。
使用SDL编译应用程序时遇到此错误。这是由SDL在SDL_main.h中定义其自己的主要功能引起的。为了防止SDL定义主要功能,必须在包含SDL.h标头之前定义SDL_MAIN_HANDLED宏。
生成之前,请尝试保存.c文件。我相信您的计算机正在引用文件中没有任何信息的路径。
-建立C专案时发生类似的问题
检查所有文件都包含在您的项目中:
更新cLion之后,我弹出了同样的错误。经过数小时的修改,我发现我的文件之一没有包含在项目目标中。将其添加回活动项目后,我停止获取对winmain16的未定义引用,并编译了代码。
编辑:在您的IDE中检查构建设置也是值得的。
(不确定此错误是否与最近更新了IDE有关-可能是因果关系,也可能只是相关关系。请对该要素的任何见解发表评论!)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
。有没有办法做到这一点,Eclipse CDT
因为我没有使用命令行。感谢