The entry point is the bit of code where execution of a program starts. Every Elements project that has an
OutputType type of
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.
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
Int32, or optionally no return type (
- 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
AnsiCharcontaining 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
Note that either the methods must be declared as
class method in Oxygene, and
Shared in Mercury, or they can be contained in a class that is marked as
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
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
StartupClassProject 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
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.
ApplicationMain Aspect (Cocoa)
On the Cocoa platform, the
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
UIApoplicationMain Cocoa runtime function, passing the app delegate type and the command line arguments as needed.
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.
Swift recently proposed a new
@main attribute to replace the
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
- Android Applications, similarly, are launched by the Android runtime, which will call one of possibly several
- ASP.NET and ASP.NET Core and related projects are launched and called into by the ASP.NET runtime or the web server.