Ответы:
Рассмотрим следующую программу уровня Windows API:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Теперь давайте создадим его, используя набор инструментов GNU (например, g ++), без специальных опций. Вот gnuc
только командный файл, который я использую для этого. Он предоставляет только параметры, чтобы сделать g ++ более стандартным:
C: \ тест> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ подсистема" Подсистема 00000003 (Windows CUI) C: \ тест> _
Это означает, что компоновщик по умолчанию создал исполняемый файл подсистемы консоли . Значение подсистемы в заголовке файла сообщает Windows, какие службы требуются программе. В этом случае с консольной системой программе требуется окно консоли.
Это также заставляет интерпретатор команд ждать завершения программы.
Теперь давайте создадим его с помощью подсистемы GUI , что просто означает, что программе не требуется окно консоли:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ подсистема" Подсистема 00000002 (Windows GUI) C: \ тест> _
Надеюсь, что пока все в порядке, хотя -mwindows
флаг частично задокументирован.
При сборке без этого полудокументированного флага нужно было бы более конкретно указать компоновщику, какое значение подсистемы нужно, и некоторые библиотеки импорта Windows API, как правило, должны быть явно указаны:
C: \ test> gnuc x.cpp -Wl, -подсистема, окна C: \ test> objdump -x a.exe | findstr / i "^ подсистема" Подсистема 00000002 (Windows GUI) C: \ тест> _
Это нормально работало с набором инструментов GNU.
Но как насчет набора инструментов Microsoft, то есть Visual C ++?
Что ж, сборка в качестве исполняемого файла консольной подсистемы работает нормально:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / заголовки x.exe | find / i "подсистема" | find / i "Windows" 3 подсистема (Windows CUI) C: \ тест> _
Однако с построением инструментальной цепочки Microsoft в качестве подсистемы графического интерфейса пользователя по умолчанию не работает:
C: \ test> msvc x.cpp user32.lib / ссылка / подсистема: окна x.cpp LIBCMT.lib (wincrt0.obj): ошибка LNK2019: неразрешенный внешний символ _WinMain @ 16, указанный в функции ___tmainCRTStartu п x.exe: фатальная ошибка LNK1120: 1 неразрешенные внешние C: \ тест> _
Технически это связано с тем, что компоновщик Microsoft по умолчанию нестандартен для подсистемы графического интерфейса . По умолчанию, когда подсистема является графическим пользовательским интерфейсом, компоновщик Microsoft использует точку входа в библиотеку времени выполнения, вызываемую функцию, с которой запускается выполнение машинного кода winMainCRTStartup
, которая вызывает нестандартную функцию Microsoft WinMain
вместо стандартной main
.
Хотя нет ничего страшного в том, чтобы это исправить.
Все, что вам нужно сделать, это указать компоновщику Microsoft, какую точку входа использовать, а именно mainCRTStartup
, которая вызывает стандарт main
:
C: \ test> msvc x.cpp user32.lib / ссылка / подсистема: окна / запись: mainCRTStartup x.cpp C: \ test> dumpbin / заголовки x.exe | find / i "подсистема" | find / i "Windows" 2 подсистема (графический интерфейс Windows) C: \ тест> _
Нет проблем, но очень утомительно. И так загадочно и скрыто, что большинство программистов Windows, которые в основном используют только нестандартные инструменты Microsoft по умолчанию, даже не знают об этом и ошибочно думают, что программа подсистемы графического интерфейса Windows «должна» иметь нестандартные, WinMain
а не стандартные. main
. Между прочим, с C ++ 0x у Microsoft возникнут проблемы с этим, поскольку компилятор должен затем рекламировать, является ли он автономным или размещенным (при размещении он должен поддерживать стандарт main
).
В любом случае, это причина, по которой g ++ может жаловаться на WinMain
отсутствие: это глупая нестандартная функция запуска, которую инструменты Microsoft требуют по умолчанию для программ подсистемы графического интерфейса.
Но, как вы можете видеть выше, g ++ не имеет проблем со стандартом main
даже для программы подсистемы GUI.
Так в чем может быть проблема?
Ну, вы, вероятно , не хватаетmain
. И у вас, наверное, тоже нет (собственно) WinMain
! А затем g ++ после поиска main
(такого нет) и нестандартного от Microsoft 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: \ тест> _
main
или a WinMain
, или убедитесь, что соответствующий файл включен в проект. Приветствия,
main
или winmain
? Спасибо
Подводя итог вышеупомянутому сообщению Cheers и hth. - Альф, убедитесь, что у вас есть main()
или WinMain()
определили и g ++ должен поступать правильно.
Моя проблема заключалась в том, что он main()
был случайно определен внутри пространства имен.
Я столкнулся с этой ошибкой при компиляции приложения с помощью SDL. Это было вызвано тем, что SDL определил свою основную функцию в SDL_main.h. Чтобы не допустить, чтобы SDL определяла основную функцию, макрос SDL_MAIN_HANDLED должен быть определен до включения заголовка SDL.h.
Перед сборкой попробуйте сохранить файл .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
поскольку я не использую командную строку. Спасибо