Рассмотрим следующую программу уровня 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"
Subsystem 00000003 (Windows CUI)
C:\test> _
Это означает, что компоновщик по умолчанию создал консольную подсистему .Значение подсистема в заголовке файла указывает Windows, какие службы требуются программе.В этом случае для консольной системы программе требуется окно консоли.
Это также заставляет интерпретатор команд ожидать завершения программы.
Теперь давайте создадим его с Подсистема графического интерфейса , что означает, что программе не требуется консольное окно:
C:\test> gnuc x.cpp -mwindows
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\test> _
Надеемся, что пока все в порядке, хотя флаг -mwindows
только частично документирован.
Построение без этого полу-документированного флага нужно было бы более конкретно указать компоновщику, какую подсистему желать получить значение, и тогда в общем случае некоторые библиотеки импорта Windows API должны быть явно указаны:
C:\test> gnuc x.cpp -Wl,-subsystem,windows
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\test> _
Тоработал нормально, с набором инструментов GNU.
Но как насчет набора инструментов Microsoft, то есть Visual C ++?
Хорошо, сборка исполняемого файла консольной подсистемы работает нормально:
C:\test> msvc x.cpp user32.lib
x.cpp
C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
3 subsystem (Windows CUI)
C:\test> _
Однако по умолчанию сборка инструментов Microsoft в качестве подсистемы GUI не работает:
C:\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals
C:\test> _
Технически это связано с тем, что MicrosoftInker является нестандартным по умолчанию для подсистемы GUI .По умолчанию, когда подсистема имеет GUI, компоновщик Microsoft использует библиотеку времени выполнения точка входа , функцию, с которой начинается выполнение машинного кода, которая называется winMainCRTStartup
, которая вызывает нестандартный Microsoft WinMain
вместо стандартного main
.
Нет ничего сложного в том, чтобы это исправить.
Все, что вам нужно сделать, это сообщить компоновщику Microsoft, какую точку входа использовать, а именно mainCRTStartup
, что вызывает стандарт main
:
C:\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp
C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
2 subsystem (Windows GUI)
C:\test> _
Без проблем, но очень утомительно.И настолько загадочные и скрытые, что большинство программистов Windows, которые в основном используют только нестандартные инструменты Microsoft по умолчанию, даже не знают об этом и по ошибке думают, что программа подсистемы Windows GUI «должна» иметь нестандартные WinMain
вместо стандартного main
.Попутно, с C ++ 0x у Microsoft возникнет проблема с этим, поскольку компилятор должен затем объявить, является ли он автономным или размещенным (при размещении он должен поддерживать стандарт main
).
В любом случае, этопричина, по которой g ++ может жаловаться на отсутствие WinMain
: это глупая нестандартная функция запуска, которая требуется инструментам Microsoft по умолчанию для программ подсистемы GUI.
Но, как вы можете видеть выше,У g ++ нет проблем со стандартом main
даже для программы с подсистемой графического интерфейса.
Так в чем же проблема?
Ну, вы, вероятно, отсутствует a main
.И у вас, вероятно, тоже нет (правильного) WinMain
!И затем g ++, после поиска main
(нет такого) и нестандартного Microsoft WinMain
(нет такого), сообщает, что последний отсутствует.
Тестирование с пустым источником:
C:\test> type nul >y.cpp
C:\test> gnuc y.cpp -mwindows
c:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): undefined referen
ce to `WinMain@16'
collect2: ld returned 1 exit status
C:\test> _