Как я могу написать приложение для Windows без использования WinMain?

Приложения Windows GUI, написанные на C / C ++, имеют WinMain в качестве точки входа (а не main). Насколько я понимаю, компилятор генерирует «основную» функцию, которая будет вызываться средой выполнения C. Эта «основная» функция устанавливает необходимую среду для графического интерфейса пользователя и вызывает WinMain (с указанием дескрипторов экземпляра и т. Д.).

Короче говоря, я считаю, что запуск консоли и приложения с графическим интерфейсом отличается следующим образом:

Консольное приложение: C Runtime -> 'main' функция (написана вручную)

Приложение с графическим интерфейсом пользователя: C Runtime -> 'main' функция (сгенерированная компилятором) -> 'WinMain' function (ручная кодировка)

Я хотел бы как проверить это понимание, так и узнать, как я могу вручную написать графический интерфейс Windows с помощью только «основной» функции (т.е. без необходимости писать WinMain).


person Matthew Murdoch    schedule 19.02.2009    source источник


Ответы (3)


У вас неправильное понимание. Разница между main и WinMain, помимо некоторого отличного кода инициализации, заключается в переданных ему параметрах.

main выглядит так:

int main(int argc, char* argv[]);

Пока WinMain выглядит так:

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
);

Что-то должно настроить эти параметры и выполнить вызов, и это код запуска. Когда вы компилируете и связываете программу, один из параметров компоновщика является точкой входа, и это будет, в зависимости от консоли или приложения с графическим интерфейсом, другой бит кода запуска.

Вы, конечно, можете написать свой собственный код запуска, просто войдите в свой исходный каталог Visual C ++, и вы найдете код запуска, он называется crt0.c и находится в каталоге VC \ crt \ src.

person Erik Funkenbusch    schedule 19.02.2009

Используя Just main, вы не можете кодировать Winmain. Для обоснования следующие утверждения были взяты из http://blogs.msdn.com/oldnewthing/archive/2007/12/03/6644060.aspx

[В программировании Windows,] Почему точка входа приложения не была названа главной? Ну, во-первых, имя main уже было занято, и Windows не имела права зарезервировать альтернативное определение. Тогда не было комитета по стандартизации языка Си; C был тем, что сказал Деннис, и вряд ли было гарантировано, что Деннис предпримет какие-либо особые шаги для сохранения совместимости исходного кода Windows в любой будущей версии языка C. Поскольку K&R не указывал, что реализации могут расширять приемлемые формы функции main, вполне возможно, что существовал законный компилятор C, который отклонял программы, которые неправильно объявляли main. Текущий стандарт языка C явно разрешает альтернативные определения для конкретной реализации для main, но требование, чтобы все компиляторы поддерживали эту новую версию для Windows для компиляции программ Windows, неоправданно ограничило бы набор компиляторов, которые вы могли бы использовать для написания программ Windows.

Если вам удалось преодолеть это препятствие, у вас возникнет проблема, заключающаяся в том, что версия main для Windows должна быть примерно такой:

int main(int argc, char *argv[], HINSTANCE hinst,
         HINSTANCE hinstPrev, int nCmdShow);

Из-за способа связывания C все вариации функции должны были согласовывать общие параметры. Это означает, что версия для Windows должна будет добавить свои параметры в конец самой длинной существующей версии main, а затем вам придется скрестить пальцы и надеяться, что язык C никогда не добавлял другую альтернативную версию main. Если вы пошли по этому пути, скрещенные пальцы не помогли вам, потому что оказалось, что третий параметр был добавлен в основной некоторое время спустя, и он противоречил вашей версии для Windows.

Предположим, вам удалось убедить Денниса запретить использование этой трехпараметрической версии main. Вам все равно нужно придумать эти первые два параметра, а это означает, что код запуска каждой программы должен содержать синтаксический анализатор командной строки. В те времена, когда было 16 бит, люди старались сохранить каждый байт. Сказав им: «Ой, и все ваши программы будут на 2 КБ больше», вероятно, вы не сделаете много друзей. Я имею в виду, что это четыре сектора ввода-вывода с дискеты!

Но, вероятно, причина, по которой точке входа Windows было присвоено другое имя, заключается в том, чтобы подчеркнуть, что это другая среда выполнения. Если бы он назывался main, люди брали бы программы на C, разработанные для консольной среды, бросали их в свой компилятор Windows, а затем запускали бы с катастрофическими результатами.

Надеюсь, это развеет ваши сомнения.

person lakshmanaraj    schedule 19.02.2009

Это работает наоборот. Есть статически связанный объектный файл, который поставляется с компилятором, который содержит фактическую точку входа. Эта точка входа выполняет инициализацию, а затем вызывает вашу точку входа (например, WinMain).

То, что ожидает эта статическая часть, можно настроить. Например, в Visual Studio в настройках компоновщика есть поле для имени точки входа.

person sharptooth    schedule 19.02.2009
comment
Итак, каков порядок выполнения в случаях приложения консоли и GUI? Отличается ли статическая часть в этих двух случаях? Какое место занимает среда выполнения C? - person Matthew Murdoch; 19.02.2009
comment
Сначала выполняется статическая часть, затем вызывается точка входа, реализованная пользователем. Они могут быть разными или одинаковыми, но компоновщик может связать вызов с разными точками входа в зависимости от настроек. Вы можете думать об этой статической части как о части среды выполнения C. - person sharptooth; 19.02.2009