Відповіді:
Розглянемо наступну програму на рівні 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 "^ підсистема" Підсистема 00000003 (Windows CUI) C: \ test> _
Це означає, що за замовчуванням лінкер створив виконується консольну підсистему . Значення підсистеми у заголовку файлу повідомляє Windows, які послуги потрібні програмі. У цьому випадку, за допомогою консольної системи, програмі потрібне вікно консолі.
Це також змушує інтерпретатора команд чекати завершення програми.
Тепер давайте побудуємо її за допомогою підсистеми GUI , що просто означає, що програмі не потрібне вікно консолі:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ підсистема" Підсистема 00000002 (графічний інтерфейс Windows) C: \ test> _
Сподіваємось, це все нормально, хоча -mwindows
прапор просто напівдокументований.
Будуючи без цього напівдокументованого прапора, потрібно було б конкретніше сказати лінкеру, яку підсистему цінує одне бажання, а деякі бібліотеки імпортування API API потрібно взагалі чітко вказати:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ підсистема" Підсистема 00000002 (графічний інтерфейс Windows) C: \ test> _
Це працювало чудово, за допомогою інструментального ланцюжка GNU.
А як щодо ланцюжка інструментів Microsoft, тобто Visual C ++?
Що ж, створення файлів як консольної підсистеми виконується добре:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> дампбін / заголовки x.exe | find / i "підсистема" | find / i "Windows" 3 підсистема (Windows CUI) C: \ test> _
Однак, якщо побудова інструментальної мережі Microsoft як підсистема GUI не працює за замовчуванням:
C: \ test> msvc x.cpp user32.lib / link / підсистема: windows x.cpp LIBCMT.lib (wincrt0.obj): помилка LNK2019: невирішений зовнішній символ _WinMain @ 16 з посиланням на функцію ___tmainCRTStartu p x.exe: фатальна помилка LNK1120: 1 невирішені зовнішні C: \ test> _
Технічно це пов’язано з тим, що лінкер Microsoft за замовчуванням для підсистеми GUI є нестандартним . За замовчуванням, коли підсистемою є графічний інтерфейс, тоді лінкер Microsoft використовує точку введення бібліотеки часу виконання , функцію, при якій починається виконання машинного коду, що називається winMainCRTStartup
, що викликає нестандартне, WinMain
а не стандартне main
.
Немає нічого серйозного, щоб виправити це.
Все, що вам потрібно зробити, - це повідомити лінкеру Microsoft, яку точку входу використовувати, а саме mainCRTStartup
, який стандартний виклик main
:
C: \ test> msvc x.cpp user32.lib / link / підсистема: windows / entry: mainCRTSзапуск x.cpp C: \ test> дампбін / заголовки x.exe | find / i "підсистема" | find / i "Windows" 2 підсистема (інтерфейс Windows) C: \ test> _
Без проблем, але дуже нудно. І настільки прихованим і прихованим, що більшість програмістів Windows, які здебільшого використовують лише нестандартні інструменти Microsoft за замовчуванням, про це навіть не знають, і помилково думають, що програма підсистеми Windows GUI "повинна" мати нестандартну WinMain
замість стандартної main
. Мимоволі з C ++ 0x у Microsoft виникне проблема з цим, оскільки компілятор повинен рекламувати, незалежно від того, чи він є вільним, так і розміщеним (коли він розміщений, він повинен підтримувати стандарт main
).
У будь-якому випадку, це причина, чому g ++ може скаржитися на WinMain
відсутність: це нерозумна нестандартна функція запуску, яку потрібні інструменти Microsoft за замовчуванням для програм підсистеми GUI.
Але, як ви бачите вище, g ++ не має проблем із стандартом main
навіть для програми підсистеми GUI.
То в чому може бути проблема?
Ну, ви, ймовірно , що не вистачаєmain
. І у вас, мабуть, немає (належного) WinMain
! А потім g ++ після пошуку main
(немає такого) та нестандартного WinMain
(немає такого) Microsoft повідомляє, що останнього немає.
Тестування з порожнім джерелом:
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 :(. текст + 0xd2 ): невизначене посилання Це до `WinMain @ 16 ' collection2: ld повернув 1 статус виходу C: \ test> _
main
або a WinMain
, або переконайтеся, що відповідний файл включений у проект. Ура,
main
чи winmain
? Спасибі
Узагальнити вищезазначений пост Cheers and hth. - Альф, переконайся, що ти маєш main()
або WinMain()
визначив, і g ++ має робити правильно.
Моя проблема полягала в тому, що вона main()
була визначена всередині простору імен випадково.
Я зіткнувся з цією помилкою під час компіляції моєї програми з SDL. Це було викликано SDL, визначаючи його основну функцію в SDL_main.h. Щоб запобігти визначенню SDL основної функції, перед включенням заголовка SDL.h слід визначити макрос SDL_MAIN_HANDLED.
Спробуйте зберегти свій .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
оскільки я не використовую командний рядок. Спасибі