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 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 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