The Entry Point of a project is the piece of code where execution starts when the application is launched. Entry points can exist only in "Executable" project types, but not in libraries, since libraries will not be launched directly.
There are three ways to declare an entry point for an executable:
Like the program unit in classic Pascal, Oxygene allows a single source file in the project to define an entry point by having the begin keyword and code statements before the end. that closes the file.
Any type of code can be placed in this begin/end pair. The code is considered to not be part of any class, but can of course access all globally available identifiers, including any Types declared in or referenced by the project, as well as any Globals if that option is enabled. It is common (but by no means required) to place the entry point in a source file called "Program.pas".
One downside of this form of entry point is that that no platform-agnostic access to any command line parameters is provided, although all platforms (and Sugar) provide APIs to access the command line, if necessary:
- .NET: System.Environment.Commandline: String
- Cocoa: NSProcessInfo.arguments: NSArray (of String)
- Java: System.getProperty('sun.java.command') — only supported in some scenarios
- Sugar: (TODO: document Sugar API for this)
The interface and implementation sections are optional in the file declaring this entry point, but only when there's no further code (such as type declarations or global methods) preceding the entry point.
namespace MyProject; begin Console.WriteLine('The magic happens here.'); end.
A static Main() Method
Alternatively, the entry point can be provided by declaring a public static method called "Main" on one of the public classes in the project. This method must have one of the following signatures, and either the method itself (via the class keyword) or the entire class (via the static keyword) must be declared static:
- method Main;
- method Main: Int32;
- method Main(aArguments: array of String);
- method Main(aArguments: array of String): Int32;
As you can see, the "Main" method can optionally provide a 32-bit (regardless of platform-bitness) Integer result type that will function as the process' exit code, and it can optionally provide access to the command line arguments passed to the executable.
If no result type is defined, the process will exit with 0.
In addition, on Cocoa only, either of the following two signatures is also valid. Do note that in contrast to the above, a Main method defined as below will receive the executable name at index 0 of the aArguments array, and the actual arguments starting at index 1. aArgumentCount will reflect that, of course:
- method Main(aArgumentCount: Int32; aArguments: ^^AnsiChar);
- method Main(aArgumentCount: Int32; aArguments: ^^AnsiChar): Int32;
Also, on .NET only, a single argument of type String is also allowed, and will receive the entire command line as one unified string:
- method Main(aArguments: String);
- method Main(aArguments: String): Int32;
We recommend using the platform-independent entry-point signatures wherever possible.
Global Main() Method
If Globals are enabled (which we do not recommend), a global method called "Main" may be defined as the entry point, following the same conventions as outlined in the previous section.
Multiple Entry Points
For obvious reasons, an executable cannot have multiple entry points, and Oxygene will behave as follows if multiple entry points are found:
- a single begin/end. entry point will take precedence over and ignore the existence of any "Main" methods.
- multiple begin/end. entry points or multiple "Main" methods will cause a compiler error.
To dedicate a specific Main method to the entry point for scenarios when more than one class contains such a method, the name of the proper class can be specified as the Startup object on the Application tab of Project Properties.