Entry Point
The entry point is the bit of code where execution of a program starts. Every Elements project that has an OutputType
type of Executable
, Exe
or (on Windows) WinExe
must define declare an entry point, in order to successfully compile and launch.
Library projects and other non-executable projects do not require an entry point.
There are several ways of declaring the entry point for your project, some explicit and some more implicit. Let's have a look.
A Static Main()
Method
The most common way to create an entry point for your project is to have a single static method called Main
that contains the code that should run when your executable launches.
It does nit matter what class this method is defined in (a common convention in Elements' templates is Program
), but it must adhere to a few conventions:
- It must be named
Main
(case does not matter, even in the case-sensitive languages) - It must match of of a set of allowed signatures (see below)
- It must be marked as static, be in a static class, or be global.
The signature of the Main
method must adhere to the following rules
- It may have an return type of
Integer
/int
/Int32
, or optionally no return type (Void
) - It can be parameterless, accepts as single parameter a Native Dynamic (unsized) Array of String or (on the native platforms) two C-style parameters, the count of arguments and an array of pointer to an
AnsiChar
containing the parameters.
class method Main;
class method Main: Integer;
class method Main(aArguments: array of String);
class method Main(aArguments: array of String): Integer;
class method Main(aCount: Integer; aArguments: array of ^AnsiChar);
class method Main(aCount: Integer; aArguments: array of ^AnsiChar): Integer;
public static void Main()
public static void Main(string[] arguments)
public static void Main(int count, AnsiChar *arguments[])
public static int Main()
public static int Main(string[] arguments)
public static int Main(int count, AnsiChar *arguments[])
public static func Main()
public static func Main() -> Int
public static func Main(_ arguments: String[]) // note, not [String]
public static func Main(_ arguments: String[]) -> Int
public static func Main(_ count: Int, _ arguments: UnsafePointer<AnsiChar>[])
public static func Main(_ count: Int, _ arguments: UnsafePointer<AnsiChar>[]) -> Int
public static void Main()
public static void Main(string[] arguments)
public static int Main()
public static int Main(string[] arguments)
Public Shared Sub Main()
Public Shared Sub Main(aArguments As String())
Public Shared Sub Main(aCount As Integer, aArguments As Ptr(Of AnsiChar)())
Public Shared Function Main: Integer
Public Shared Function Main(aArguments As String()): Integer
Public Shared Function Main(aCount As Integer, aArguments As Ptr(Of AnsiChar)()): Integer
The variants with two parameters are supported on Cocoa and the Island-backed platforms only, and only in languages that support Pointers.
Note that either the methods must be declared as static
(optionally class method
in Oxygene, and Shared
in Mercury, or they can be contained in a class that is marked as static
(again, Shared
in Mercury). Also note that in the Java language, the static
keyword on a class does not mark it static but has a different meaning, so in Java, the method itself must be marked static
.
Resolving Ambiguity
If for some reason a project contains multiple candidates for an entry point, the compiler will by default emit an error and fail the compilation. You can set the StartupClass
Project Setting to the name of the class containing the proper Main
function; the Main
method in that class must be non-ambiguous.
Simplified Entry Point in Oxygene
In Oxygene, rather than explicitly declaring a Main
method, the project can have a single source unit where the final end.
is preceded by the begin
keyword and zero or more statements that make up the entry point:
namespace MyProject;
uses
Foo;
// more types and methods could be here
begin
writeLn('The magic happens here');
end.
Simplified Entry Point in C#, Swift and Mercury
In C#, Swift and Mercury rather than explicitly declaring a static Main
method, the project can have a single source unit that contains one or more statements in the global scope (i.e. not contained in a type or func
):
using Foo;
// more types and code could be here
writeLn("The magic happens here");
// more types and methods could be here
import Foo
// more types and code could be here
writeLn("The magic happens here");
// more types and funcs could be here
Imports Foo
' more types and code could be here
writeLn('The magic happens here');
' more types and Subs could be here
If variables, functions/methods or type declarations are found after the first statement, they will be treated not as globals, but as declared nested within the implied Main
function, will behave as local variables/types/closures and have access to the values of previously declared locals, as if the entire body from the first statement to the end of the file were enclosed in a Main()
method block.
Swift Base Library declares the following two global properties that give you access to the arguments that were passed to the executable at runtime, even when using the simplified entry point:
public let C_ARGC: Int
public let C_ARGV: [String]
Technically, these would also be available form anywhere in code, and they are also available to other languages, if the project references the SBL.
In C# and Mercury, am implicit local variable/parameter named args
is available, providing optional access to the array of command line parameters.
The ApplicationMain
Aspect (Cocoa)
On the Cocoa platform, the NSApplicationMain
/UIApplicationMain
aspect can be applied to a single class in the project. That class will then be regarded as the App Delegate, and the Aspect will automatically emit a proper Main()
method during compilation that calls the corresponding NSApplicationMain
or UIApoplicationMain
Cocoa runtime function, passing the app delegate type and the command line arguments as needed.
The App.xaml
File (WPF)
In WPF projects on .NET, a .xamnl
file marked with the ApplicationDefinition
will contribute to a sub-class of type System.Windows.Application
and automatically generate a Main()
method that will instantiate and call the appropriate members of that class on startup.
Future Extensions
Swift recently proposed a new @main
attribute to replace the NSApplicationMain
or UIApoplicationMain
aspects covered above. Support for this new Aspect is planned, but not implemented yet. (SE-0281 @main: Type-Based Program Entry Points, bugs://84619).
Projects without Entry Point
Some project types do not require an entry point, because thay are not, technically, executables that can be launched directly by the OS:
- Library, StaticLibrary and DynamicLibrary projects cannot launch ad thus, as mentioned above, do not require entry points.
- WebAssembly Modules are not launched directly but technically are dynamic libraries loaded by the browser or Node.js runtime, which communicates with the code via other means than a
Main()
method - Android Applications, similarly, are launched by the Android runtime, which will call one of possibly several
Activity
classes - ASP.NET and ASP.NET Core and related projects are launched and called into by the ASP.NET runtime or the web server.
See Also
StartupClass
Project SettingNSApplicationMain
/UIApplicationMain
- Top-Level Statements in Mercury