Island/Delphi

New in version 12, Elements allows you to reference and directly work with Delphi-compiled code and have access to the full Delphi type system and APIs from your projects on native Windows, Linux and macOS, on the Island platform.

This is achieved by importing Delphi package files (.dcp) into .fx files that make their content available to the Elements compiler. The resulting binary will then reference and depend on the used packages (.bpls).

This includes support for Delphi's base class libraries (including RTL, VCL, dbGo, FireMonkey and everything else), as well as third-party packages and even your own Delphi-compiled packages.

In Elements code, all types, globals and functions/procedures are directly accessible and usable as-is, underneath the Delphi namespace.

Prerequisites!

Before using Delphi libraries, you will need to import the base SDK for the version(s) of Delphi you work with, as described under Setup.

Using a Delphi SDK in your Project

Using a Delphi SDK in your project is as simple as setting the "Delphi SDK" project setting to the name of Delphi SDK you have imported, for example <DelphiSDK>Delphi 11</DelphiSDK>. This setting becomes available in the IDE for compatible Island project types, as soon as one or more Delphi SDK has been imported.

After setting this, a few things will happen automatically, in the IDE and during build:

  • Your project will get an implicit reference to Delphi.rtl.fx, the core package.
  • Your project will get an implicit reference to Island.DelphiSupport.fx, our small support library for interaction with Island RTL and Delphi's object model.
  • Your project will emit additional errors, if you are targeting architectures that your Delphi version does not support (e.g. 64-bit Windows or Linux before Delphi 10.4, macOS before Delphi 10.3 (which added 64bit support, a decade late) or Apple Silicon macOS before Delphi 11. If necessary, you will need to set the Architecture Project Setting to limit your target architectures.

Delphi.rtl.fx contains the bulk of the basic Delphi APIs. You can add references to any of the other Delphi packages, as you need – for example Delphi.vcl.fx (for Windows), Delphi.dbrtl.fx for database access, and so on – via the standard Add References UI.

Note that all imported packages are prefixed with "Delphi., to avoid name collisions with other standard Elements or OS references (or frameworks, on macOS). This applies to the reference name and the namespace(s) contained within.

Using Delphi APIs

Once referenced, all the APIs exposed by a package are available to your code, the same they would be in Delphi, and the same as any other native Elements types and functions are. All Delphi-imported types have their namespace (or unit name, for older Delphi versions) prefixed with "Delphi.", again to avoid name collisions and overlap.

For example, you could add Delphi.System.SysUtils to your uses clause, and start using SysUtils APIs in your code. Add Delphi.Vcl.Forms to start using VCL classes such as TForm.

You can also set "Default "uses" Prefixes" in project settings to, just like in Delphi, flatten the namespace hierarchy.

From there, all classes, types and global functions from the Delphi packages you have chosen to reference are available, and should be fully usable.

The Delphi Object Model

As you might know, the Island compiler backed suports different Object Models for platform interaction. By default classes you implement in Elements use the garbage-collected Island object mode, native to Elements, but on Cocoa you have long been able to also use Cocoa and Swift object models for native Objective-C and Swift types, which are reference counted.

Similarly, all classes, interfaces and records imported from Delphi use the Delphi Object Model, which means they live in a separate class hierarchy from your Elements-native types, and all the classes untimately descend from Delphi.System.TObject.

Like in Delphi itself, Delphi object model classes in Elements are not automatically memory-managed – meaning you have to track their life-time, and manually call Free, Destroy, FreeAndNil or dispose of them by other means.

Any classes you define that descend from Delphi-imported types will automatically use the Delphi object mode, as well. You can also explicitly mark a class to use this model by either adding the [Delphi] attribute to it, or explicitly specifying TObject (or one of its descendants) as the ancestor.

You can also set the "Default Object Model" setting for your project to Delphi to have all your types use that model by default, even when no ancestor or attribute is specified. This might be recommended for porting entire existing code bases over, or writing code that uses Delphi APIs more than it uses native Elements or platform APIs.

Read more about the Delphi Object Model.

Strings

Elements provides extensive support for delphi-compatible String types, which you can read more about here: Delphi String Support.

Do note that, by default, strings – such as those created from literals – are still Island-level string types, part of the Island object model tree, and responding to the APIs available on that type.

Island's native String and Delphi's String types provide operators for casting seamlessly between the two, but such casts will have a conversion cost.

The DelphiString type is provided for working Delphi-type strings and is compatible with being passed into and received from Delphi APIs that take strings. It provides the same usage semantics as strings do in Delphi, such as one-based access, copy-on-write semantics, and compatibility with PChar, and is fully memory-compatible with Delphi strings.

Importing Third Party Components and Packages

...

Importing Your Own Packages

...

Forms and .DFMs

The Elements tool chain knows about .dfm, .lfm and .fmx form files, and it will compile text-based forms to binary and perform the necessary steps to embed them into your executable for the VCL or FireMonkey classes to find at runtime.

The recommended way for this is to add .dfm, .lfm and .fmx to your project with a Build Action of "EmbeddResource" (which the Delphi project import will do for you), but the build tool chain can also optionally look for {$R resource tags in your Oxygene source files and pull in resource files from that.

Forms embedded in this way are compatible both with Delphi's VCL/FireMonkey library and the limited VCL support in the (unrelated) Delphi RTL native-Elements compatibility library.

Use Cases for Delphi SDKs

The availability of Delphi SDKs to Elements projects brings a whole slew of possibilities for the migration of Delphi projects to Elements.

  • You can simply reference Delphi packages to use your favorite Delphi APIs and classes you are familiar with, in your Elements code.
  • You can move/copy over code from Delphi to Oxygene more seamlessly, as all the APIs it relies on are there.
  • You can even move entire Delphi projects to Oxygene, keep using the VCL and all your third party components, while at the same time still benefitting from the more advanced Oxygene language.

And, of course Delphi SDK support is not limited to just Oxygene – you can use these APIs, and even descend from Delphi classes (such as to implement a new TForm, from all six Elements languages!

See Also