Метод Main или точка входа в программу
Если говорить простым языком, то точка входа это место, в языке c# представленное статическим методом Main, с которого начинает выполнение ваша программа при условии, что данная программа (приложение) является исполняемым, то есть будет иметь расширение (.exe).
То есть даже если ваш класс или несколько классов будут содержать 20, 30 или более разных методов, всё равно выполнение программы начинается со статического метода Main.
В вашем приложении Вы так же можете создать несколько классов и в каждый из них поместить статический метод Main, в результате ваша программа будет иметь несколько точек входа. Данный способ можно применять, например, для отладки ваших приложений при большом количестве исходного кода.
Но, тогда возникает вопрос, если точек входа несколько, тогда с какого места начнёт выполнение ваша программа?
Для примера добавим в исходный код нашей программы ещё один класс по имени Test, внутри которого поместим точно такой же статический метод Main, как в классе Program.
C#:
namespace Example
{
class Program
{
static void Main()
{
System.Console.WriteLine("метод 1");
System.Console.ReadLine();
}
}
class Test
{
static void Main()
{
System.Console.WriteLine("метод 2");
System.Console.ReadLine();
}
}
}
Если сейчас попытаться выполнить код, то компилятор выдаст ошибку:
Код:
Error Program 'E:c# projectSLLab1objx86DebugLab1.exe'
has more than one entry point defined: 'Example.Program.Main()'.
Compile with /main to specify the type that contains the entry point.
Данная ошибка возникает, потому что в программе присутствует два статических метода Main, что приводит к возникновению конфликта, если сейчас перейти в свойства текущего проекта (картинка ниже), то можно найти пункт: startup object, который по умолчанию имеет значение: Not set.
Это значит, что если ваше приложение содержит хотя бы один статический метод Main, то тогда по умолчанию данный метод и будет являться точкой входа в программу, но если в приложении несколько таких методов, как в нашем примере, то тогда необходимо явно указать точку входа в программу.
Как явно указать точку входа?
Перейдите в окно Solution Explorer и нажмите правую кнопку мыши на имени проекта, в нашем случае имя проекта Lab1. После чего в списке выберите пункт Properties, в результате должно появиться вот такое окно.
Находим пункт startup object и в выпадающем списке явно указываем класс, который будет содержать точку входа в программу. Для примера выберем Example.Test, таким образом, мы явно укажем, что в качестве точки входа в нашей программе мы будем использовать статический метод Main, который находиться в классе Test, пространства имён Example.
Если сейчас запустить нашу программу, то получим вот такой результат.
Если точка входа не найдена, то есть наша программа не будет содержать статический метод Main, или данный метод будет иметь не правильную синтаксическую конструкцию, к примеру он не будет иметь ключевое слово static, то Вы так же получите ошибку на этапе компиляции.
Читайте также:
- Создание первого приложения на языке c#. Часть вторая.
- Как найти все цифры в строке?
- Почему у меня в Data Source нет пункта Mysql Database?
Точка входа в программу
Последнее обновление: 21.07.2021
Точка входа в программу представляет функцию, с которой начинается выполнение приложения. Для определения функции как точки входа в приложения,
применяются ряд условий:
-
Эта функция должна применять атрибут [<EntryPoint>]
-
Эта функция должна принимать один параметр – набор (а точнее массив) строк, через которые в данную функцию можно передать данные при ее вызове. (Например, при запуске приложения из командной строки)
-
Эта функция должна возвращать число типа
int
. Согласно условностям, обычно это 0 – при успешном выполнении, либо любое другое число при неудачном выполнении. -
Эта функция должна быть последней функцией в последнем компилируемом файле.
Последний компилируемый файл – это последний файл в проекте, либо последний файл в списке файлов, которые передаются компилятору при компиляции в командной строке
Как правило, эта функция называеся main, но это необязательно. Например, определим точку входа в приложение:
[<EntryPoint>] let main argv = printfn "Начало выполнения приложения" 0
Итак, данная функция применяет атрибут [<EntryPoint>]
(он указывается над определением функции). Она имеет один параметр и возвращает число.
Стоит отметить, что если параметр функции не используется, мы можем, как в общем случае, вместо него указать прочерк:
[<EntryPoint>] let main _ = printfn "Начало выполнения приложения" 0
Теперь обратимся к последнему условию: функция входа в приложение должна быть последней функций (и вообще последним опредлением в файле). То есть мы можем разместить другие конструкции,
определения значений, функций, их вызов до функции main:
let sum x y = x + y let message = "Hello F#" printfn $"{message}" [<EntryPoint>] let main _ = printfn "Функция main" 0
Но мы НЕ можем это сделать после определения функции входа в приложение:
[<EntryPoint>] let main _ = printfn "Функция main" 0 let sum x y = x + y let message = "Hello F#" printfn $"{message}"
Но в принципе в этом случае Visual Studio укажет на ошибку.
Стоит отметить, что если до функции точки входа в приложение идут вызовы других функций , то они также выполняются. В данном случае имеются ввиду
вызовы функций верхнего уровня – то есть такие вызовы функций, которые расположены вне других функций. Например, путь у нас будет следующий код программы:
let sum x y = x + y let message = "Hello F#" printfn $"{message}" printfn $"Сумма 1 и 2 равна {sum 1 2}" [<EntryPoint>] let main _ = printfn "Функция main" 0
В данном случае мы получим следующий консольный вывод:
Hello F# Сумма 1 и 2 равна 3 Функция main
Таким образом, мы видим, что все выражения, которые идут до функции main, также были выполнены.
Однако если до функции входа в приложение идут только определения функций без их вызовов, то эти функции не выполняются:
let sum x y = printfn $"Сумма {x} и {y} равна {x + y}" let printMessage _ = printfn "Hello F#" [<EntryPoint>] let main _ = printfn "Функция main" 0
Так, в данном случае будет выполняться только функция main, поскольку именно она является точкой входа в приложения. Соответственно консольный вывод программы:
Чтобы выполнить подобные функции, нам надо вызвать их в функции main:
let sum x y = printfn $"Сумма {x} и {y} равна {x + y}" let printMessage _ = printfn "Hello F#" [<EntryPoint>] let main _ = printfn "Функция main" sum 1 2 printMessage() 0
Консольный вывод программы:
Функция main Сумма 1 и 2 равна 3 Hello F#
Неявная точка входа
Выше было показано, как определять точку входа, однако в предыдущих статьях точка входа не использовалась, но код тем не менее выполнялся.
Если в коде явным образом не определено функции с атрибутом EntryPoint,
то в качестве точки входа используются все привязки значений и функций верхнего уровня, которые определены в последнем компилируемом файле.
Gouvere 19 / 19 / 8 Регистрация: 25.11.2013 Сообщений: 122 |
||||||||||||||||
1 |
||||||||||||||||
Где точка входа приложения?10.08.2014, 16:14. Показов 2884. Ответов 6 Метки нет (Все метки)
В общем, есть 3 файла. Разбирать их содержимое не нужно, меня интересует только конструкции include. Итак, файл main.cpp:
Файл Point.h:
И файл Point.cpp:
Так вот в чем проблема. Я недавно перешел с Web-программирования на системное. Там одна точка входа(например, index.php), остальные файлы просто подгружаются через include. И у меня возникает вопрос, почему это приложение из 3 файлов работает?
а он все-равно подгрузился Почему так? В Visual Studio у меня следующая картина:
0 |
87 / 68 / 19 Регистрация: 07.03.2011 Сообщений: 169 |
|
10.08.2014, 16:22 |
2 |
Сообщение было отмечено Gouvere как решение РешениеТочка входа – функция main. Связи настроил линкер, поэтому сущности, определённые в файле Point.cpp, могут использоваться в функции main. Добавлено через 1 минуту
1 |
porshe |
10.08.2014, 16:27
|
Не по теме:
при запуске собранной программы выскочит сообщение, мол, не найдена точка входа. интересно, а откуда ОС узнаёт где находится точка входа?
0 |
Убежденный Ушел с форума 16458 / 7422 / 1186 Регистрация: 02.05.2013 Сообщений: 11,617 Записей в блоге: 1 |
||||
10.08.2014, 16:30 |
4 |
|||
Сообщение было отмечено Gouvere как решение Решение
Но я нигде не писал
а он все-равно подгрузился Среда сделала это за вас:
В Visual Studio у меня следующая картина: P.S. Не по теме:
интересно, а откуда ОС узнаёт где находится точка входа? Из заголовка exe (поле называется EntryPoint, есть в спецификации
2 |
porshe |
10.08.2014, 16:32
|
Не по теме:
Из заголовка exe спасибо
0 |
Пес войны 111 / 88 / 22 Регистрация: 23.02.2012 Сообщений: 653 |
|
10.08.2014, 17:06 |
6 |
Из заголовка exe (поле называется EntryPoint, есть в спецификации все таки там функция Start указана наверное…)
0 |
19 / 19 / 8 Регистрация: 25.11.2013 Сообщений: 122 |
|
10.08.2014, 17:12 [ТС] |
7 |
Всем спасибо) Попробую собрать из командной строки)
0 |
Время на прочтение
6 мин
Количество просмотров 27K
Многие думают, что точки входа это такие инструкции в setup.py, которые позволяют сделать пакет доступным для запуска из командной строки. Это, в целом, верно, но возможности точек входа не ограничиваются этим.
Ниже я покажу как можно реализовать систему плагинов для пакета, чтобы другие люди могли с ним взаимодействовать или, например, расширять его функциональность динамически.
Осторожно: специфический юмор далее по тексту.
ООО «Змейка»
Поздравляю! Вас только что назначили главой ООО «Змейка». Это очень ответственная должность, ударить в грязь лицом нельзя, а значит, нужно как можно скорее дать указание отделу разработки приступить к созданию прототипа продукта. И вот, лучшие умы компании начинают работу над snek.py:
ascii_snek = """
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
"""
def main():
print(ascii_snek)
if __name__ == '__main__':
main()
Чуть позже, на собрании акционеров вы с гордостью демонстрируете первые результаты!
$ python snek.py
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
Змейка как сервис
К сожалению, рядовой потребитель пока ещё не освоил Python и хочет запускать программу из консоли, не думая об интерпретаторе или местоположении snek.py. Что ж, наши лучшие специалисты на то и лучшие, что смогли запаковать скрипт так, чтобы он автоматически создавал консольную команду при установке.
Для создания распространяемого пакета нам нужен файл setup.py, где содержится информация о зависимостях, лицензии и т.д. Помимо этого, в нём можно указать точки входа:
from setuptools import setup
setup(
name='snek',
entry_points={
'console_scripts': [
'snek = snek:main',
],
}
)
console_scripts, как пояснили специалисты, специальная точка входа. setuptools читает её элементы как “<консольный скрипт> = <путь к питоновскому объекту>”, создавая для каждого элемента консольную утилиту при установке пакета.
Пока что давайте установим скрипт из исходников:
$ python setup.py develop
running develop
running egg_info
writing snek.egg-infoPKG-INFO
writing dependency_links to snek.egg-infodependency_links.txt
writing entry points to snek.egg-infoentry_points.txt
writing top-level names to snek.egg-infotop_level.txt
reading manifest file 'snek.egg-infoSOURCES.txt'
writing manifest file 'snek.egg-infoSOURCES.txt'
running build_ext
Creating c:program files (x86)py36-32libsite-packagessnek.egg-link (link to .)
snek 0.0.0 is already the active version in easy-install.pth
Installing snek-script.py script to C:Program Files (x86)Py36-32Scripts
Installing snek.exe script to C:Program Files (x86)Py36-32Scripts
Installing snek.exe.manifest script to C:Program Files (x86)Py36-32Scripts
Installed c:usersrachumnotebooks
Processing dependencies for snek==0.0.0
Finished processing dependencies for snek==0.0.0
На конференции, посвящённой итогам года, вы выступаете, демонстрируя новейшую разработку:
$ snek
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
Змейка в каждый дом
Змейка завоёвывает мир. Компания провела IPO и была оценена в рекордные 60 миллиардов долларов. Хипстеры требуют новую, стильную, модную и молодёжную змейку. А раз есть спрос, будет и предложение:
"""Печатает ASCII змейку.
Использование:
snek [--type=TYPE]
"""
import docopt
normal_snek = """
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
"""
fancy_snek = """
_,..,,,_
'``````^~"-,_`"-,_
.-~c~-. `~:. ^-.
`~~~-.c ; `:. `-, _.-~~^^~:.
`. ; _,--~~~~-._ `:. ~. .~ `.
.` ;' .:` `: `:. ` _.:-,. `.
.' .: :' _.-~^~-. `. `..' .: `. '
: .' _:' .-' `. :. .: .'`. : ;
: `-' .:' `. `^~~^` .:. `. ; ;
`-.__,-~ ~-. ,' ': '.__.` :'
~--..--' ':. .:'
':..___.:'
"""
def get_sneks():
return {
'normal': normal_snek,
'fancy': fancy_snek,
}
def main():
args = docopt.docopt(__doc__)
snek_type = args['--type'] or 'normal'
print(get_sneks()[snek_type])
if __name__ == '__main__':
main()
Хипстеры в восторге:
$ snek
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
$ snek --type fancy
_,..,,,_
'``````^~"-,_`"-,_
.-~c~-. `~:. ^-.
`~~~-.c ; `:. `-, _.-~~^^~:.
`. ; _,--~~~~-._ `:. ~. .~ `.
.` ;' .:` `: `:. ` _.:-,. `.
.' .: :' _.-~^~-. `. `..' .: `. '
: .' _:' .-' `. :. .: .'`. : ;
: `-' .:' `. `^~~^` .:. `. ; ;
`-.__,-~ ~-. ,' ': '.__.` :'
~--..--' ':. .:'
':..___.:'
Транснациональная Змейка
Миллионы человек не мыслят свой день без змейки. Даже после поглощения Гугла ресурсов ООО «Змейка» не хватает, чтобы удовлетворять потребности пользователей по всему миру. Похоже настало время дать людям возможность создавать собственных змеек на базе нашей инфраструктуры.
"""Печатает ASCII змейку.
Использование:
snek [--type=TYPE]
"""
import docopt
import pkg_resources
normal_snek = """
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
"""
fancy_snek = """
_,..,,,_
'``````^~"-,_`"-,_
.-~c~-. `~:. ^-.
`~~~-.c ; `:. `-, _.-~~^^~:.
`. ; _,--~~~~-._ `:. ~. .~ `.
.` ;' .:` `: `:. ` _.:-,. `.
.' .: :' _.-~^~-. `. `..' .: `. '
: .' _:' .-' `. :. .: .'`. : ;
: `-' .:' `. `^~~^` .:. `. ; ;
`-.__,-~ ~-. ,' ': '.__.` :'
~--..--' ':. .:'
':..___.:'
"""
def get_sneks():
sneks = {
'normal': normal_snek,
'fancy': fancy_snek,
}
for entry_point in pkg_resources.iter_entry_points('snek_types'):
sneks[entry_point.name] = entry_point.load()
return sneks
def main():
args = docopt.docopt(__doc__)
snek_type = args['--type'] or 'normal'
print(get_sneks()[snek_type])
if __name__ == '__main__':
main()
Теперь, каждый раз когда snek запущена, она ищет других зарегистрированных в системе змеек, используя точку входа snek_types. Каждая такая змейка зарегистрирована под названием её типа, что позволяет выбирать нужную змейку в зависимости от параметров консоли.
Всё самое главное происходит внутри get_sneks. Вызов pkg_resources.iter_entry_points(‘snek_types’) позволяет пройтись по всем точкам входа, зарегистрированным под именем «snek_types» где-либо. Таким образом, любой сторонний пакет сможет в своём setup.py создать точку входа «snek_types», чтобы быть загруженным нашим скриптом.
Мы рассказали о «snek_types» нашим коллегам из ООО «Змеиные решения», и они тут же начали создавать змейку своей мечты. Вот каким получился их пакет cute_snek.py:
cute_snek = r"""
/^/^
_|__| O|
/ /~ _/
____|__________/
_______
`
| |
/ /
/ /
/ /
/ /
/ / _----_
/ / _-~ ~-_ | |
( ( _-~ _--_ ~-_ _/ |
~-____-~ _-~ ~-_ ~-_-~ /
~-_ _-~ ~-_ _-~
~--______-~ ~-___-~
"""
А вот как они реализовали свой setup.py, чтобы наша snek могла загрузить их змейку:
from setuptools import setup
setup(
name='cute_snek',
entry_points={
'snek_types': [
'cute = cute_snek:cute_snek',
],
}
)
Они зарегистрировали переменную cute_snek в модуле cute_snek под именем cute. Далее они устанавливают пакеты snek и cute_snek:
$ cd cute_snek && python setup.py develop
running develop
running egg_info
writing cute_snek.egg-infoPKG-INFO
writing dependency_links to cute_snek.egg-infodependency_links.txt
writing entry points to cute_snek.egg-infoentry_points.txt
writing top-level names to cute_snek.egg-infotop_level.txt
reading manifest file 'cute_snek.egg-infoSOURCES.txt'
writing manifest file 'cute_snek.egg-infoSOURCES.txt'
running build_ext
Creating c:program files (x86)py36-32libsite-packagescute-snek.egg-link (link to .)
cute-snek 0.0.0 is already the active version in easy-install.pth
Installed c:usersrachumcute_snek
Processing dependencies for cute-snek==0.0.0
Finished processing dependencies for cute-snek==0.0.0
Теперь, запустив snek, они могут вывести свою змейку из пакета cute_snek за счёт её динамической загрузки по точке входа:
$ snek --type cute
/^/^
_|__| O|
/ /~ _/
____|__________/
_______
`
| |
/ /
/ /
/ /
/ /
/ / _----_
/ / _-~ ~-_ | |
( ( _-~ _--_ ~-_ _/ |
~-____-~ _-~ ~-_ ~-_-~ /
~-_ _-~ ~-_ _-~
~--______-~ ~-___-~
Змейка 2.0
Пока всё внимание высшего руководства уходит на разборки с налоговой инспекцией и антимонопольной службой, отдел разработки наконец-то может выкроить немного времени на рефакторинг кода.
Главный системный архитектор понял, что если сторонние змейки могут быть загружены как плагины, значит, так же могут быть загружены и встроенные змейки.
Уберём особую обработку встроенных змеек:
--- a/snek.py
+++ b/snek.py
@@ -31,10 +31,7 @@ fancy_snek = """
"""
def get_sneks():
- sneks = {
- 'normal': normal_snek,
- 'fancy': fancy_snek,
- }
+ sneks = {}
for entry_point in pkg_resources.iter_entry_points('snek_types'):
sneks[entry_point.name] = entry_point.load()
return sneks
И взамен зарегистрируем для них универсальные точки входа:
--- a/setup.py
+++ b/setup.py
@@ -6,5 +6,9 @@ setup(
'console_scripts': [
'snek = snek:main',
],
+ 'snek_types': [
+ 'normal = snek:normal_snek',
+ 'fancy = snek:fancy_snek',
+ ],
},
)
Переустановим изменённую змейку:
$ python setup.py develop
running develop
running egg_info
writing snek.egg-infoPKG-INFO
writing dependency_links to snek.egg-infodependency_links.txt
writing entry points to snek.egg-infoentry_points.txt
writing top-level names to snek.egg-infotop_level.txt
reading manifest file 'snek.egg-infoSOURCES.txt'
writing manifest file 'snek.egg-infoSOURCES.txt'
running build_ext
Creating c:program files (x86)py36-32libsite-packagessnek.egg-link (link to .)
snek 0.0.0 is already the active version in easy-install.pth
Installing snek-script.py script to C:Program Files (x86)Py36-32Scripts
Installing snek.exe script to C:Program Files (x86)Py36-32Scripts
Installing snek.exe.manifest script to C:Program Files (x86)Py36-32Scripts
Installed c:usersrachumnotebooks
Processing dependencies for snek==0.0.0
Finished processing dependencies for snek==0.0.0
Проверим результат:
$ snek
--..,_ _,.--.
`'.'. .'`__ o `;__.
'.'. .'.'` '---'` `
'.`'--....--'`.'
`'--....--'`
$ snek --type fancy
_,..,,,_
'``````^~"-,_`"-,_
.-~c~-. `~:. ^-.
`~~~-.c ; `:. `-, _.-~~^^~:.
`. ; _,--~~~~-._ `:. ~. .~ `.
.` ;' .:` `: `:. ` _.:-,. `.
.' .: :' _.-~^~-. `. `..' .: `. '
: .' _:' .-' `. :. .: .'`. : ;
: `-' .:' `. `^~~^` .:. `. ; ;
`-.__,-~ ~-. ,' ': '.__.` :'
~--..--' ':. .:'
':..___.:'
$ snek --type cute
/^/^
_|__| O|
/ /~ _/
____|__________/
_______
`
| |
/ /
/ /
/ /
/ /
/ / _----_
/ / _-~ ~-_ | |
( ( _-~ _--_ ~-_ _/ |
~-____-~ _-~ ~-_ ~-_-~ /
~-_ _-~ ~-_ _-~
~--______-~ ~-___-~
На этом всё. Теперь вы знаете, как использовать точки входа в Python!
Выполнение программ, написанных на Java, начинается со специального метода который называется main() и входит в главный класс. В качестве главного можно использовать не только обычный class, но и интерфейс, и даже перечисление enum.
В JavaFX main класс должен реализовать интерфейс javafx.application.Applicaton.
Метод main обязательно должен быть отмечен как public и static. Также он может иметь модификатор strctfp. Ограничений на аннотации не накладывается. В методе присутствует один аргумент String[], то есть массив строк. Этот аргумент модно записать также как String…. Разницы между ними нет, в любом случае приложение компилируется в один байт код. В этом массиве передаются аргументы, передаваемые через командную строку при запуске приложения. На название массива ограничений не существует.
При запуске программы как classpath из строки команд требуется передать имя main класса. Если существует единственный файл, в нем должен присутствовать метод main.
main класс задаётся в манифесте архивного jar файла. Внутри его, в файле MANIFEST.MF, находящегося в папке META-INF, должна быть строчка с именем главного класса, например такая: Main-Class: ru.itsobes.MyClassMain. Если такой строки не будет найден, выполнение программы завершится с ошибкой «no main manfest attribute».
Если в главном классе программы будет отсутствовать main-метод, или он не будет отвечать всем необходимым требованиям, то приложение совершиться с ошибкой «Main method not found».
В апплетах входными методами являются init или start. Он в девятой версии Java апплеты были признаны устаревшими, а в одиннадцатой отменена, поэтому не стоит на них останавливаться.