Когда я пытаюсь создать программу с помощью Eclipse CDT
, я получаю следующее:
/mingw/lib/libmingw32.a(main.o): main.c:( текст + 0x106).: undefined ссылка на `WinMain @16
Почему? И как я могу решить эту проблему?
Когда я пытаюсь создать программу с помощью Eclipse CDT
, я получаю следующее:
/mingw/lib/libmingw32.a(main.o): main.c:( текст + 0x106).: undefined ссылка на `WinMain @16
Почему? И как я могу решить эту проблему?
Рассмотрим следующую программу уровня API на уровне Windows:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Теперь создадим его с помощью GNU toolchain (т.е. g++), никаких специальных опций. Здесь gnuc
- это только пакетный файл, который я использую для этого. Он предоставляет только опции, чтобы сделать g++ более стандартным:
C:\test> gnuc x.cpp C:\test> objdump -x a.exe | findstr /i "^subsystem" Subsystem 00000003 (Windows CUI) C:\test> _
Это означает, что компоновщик по умолчанию создавал исполняемый файл подсистемы консоли. Значение подсистемы в заголовке файла сообщает Windows о том, какие службы требуется программе. В этом случае с консольной системой для программы требуется окно консоли.
Это также заставляет интерпретатор команд ждать завершения программы.
Теперь создадим его с помощью подсистемы GUI, что означает, что программа не требует окна консоли:
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:\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 toolchain в качестве подсистемы GUI по умолчанию не работает:
C:\test> msvc x.cpp user32.lib /link /subsystem:windows x.cpp LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol [email protected] referenced in function ___tmainCRTStartu p x.exe : fatal error LNK1120: 1 unresolved externals C:\test> _
Технически это связано с тем, что компоновщик Microsoft не является стандартным по умолчанию для подсистемы GUI. По умолчанию, когда подсистемой является графический интерфейс, тогда Microsoft linker использует библиотеку времени выполнения , которая запускает запуск машинного кода под названием winMainCRTStartup
, который вызывает Microsoft нестандартно WinMain
вместо стандартного main
.
Нет ничего сложного, чтобы исправить это.
Все, что вам нужно сделать, - это указать Microsoft linker, для которой используется точка входа, а именно 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
. Попутно с С++ 0x у Microsoft возникнет проблема с этим, так как компилятор должен затем рекламировать, является ли он независимым или размещенным (при размещении он должен поддерживать стандарт main
).
Во всяком случае, причина, по которой g++ может жаловаться на WinMain
, отсутствует: это глупая нестандартная функция запуска, которую инструменты Microsoft по умолчанию требуют для программ подсистемы GUI.
Но, как вы можете видеть выше, g++ не имеет проблем со стандартным main
даже для программы подсистемы GUI.
Так что может быть проблемой?
Ну, вам, вероятно, не хватает 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 `[email protected]' collect2: ld returned 1 exit status C:\test> _
Подводя итог вышеупомянутому сообщению от Cheers и hth. - Alf, убедитесь, что у вас есть main()
или WinMain()
, а g++ - правильная вещь.
Моя проблема заключалась в том, что main()
был определен внутри пространства имен случайно.
Я столкнулся с этой ошибкой при компиляции моего приложения с помощью SDL. Это было вызвано тем, что SDL определяет его основную функцию в SDL_main.h. Чтобы SDL не определял основную функцию, макрос SDL_MAIN_HANDLED должен быть определен до включения заголовка SDL.h.
Попробуйте сохранить файл .c перед созданием. Я считаю, что ваш компьютер ссылается на путь к файлу без какой-либо информации внутри него.
- имел аналогичную проблему при создании проектов C