Elements RTL is an open source library for Elements that aims to create a common set of classes that can be used on all supported target platforms – .NET, Cocoa and Java – in order to enable more code sharing between these platforms. It is available for all four languages and on all four platforms.
Use of the Elements RTL library in your projects is entirely optional. By default/design, Elements projects start out working directly against the native APIs of each platform. It is your decision whether to add a reference to Elements RTL and to start using its APIs as well – usually if your intention is to create code that can be shared across platforms.
We look at Elements as a cross-platform compiler and tool for creating great apps on all platforms, and not as a tool for creating cross-platform apps.
Cross-platform apps (with some exceptions, such as back-end servers or command line utilities) suck – they settle for a "lowest common denominator" approach that makes them bad apps on all platforms. As such, we do not want developers to write cross-platform apps — that is, a single app that runs across different platforms.
What we do want to encourage (and enable) with Elements is for developers to create great apps on any platform they want. Oftentimes, this means creating separate versions of the same app for different platforms – for example two different versions of a mobile app, for iOS and Android. Or two different versions of your desktop apps, for Windows and Mac. Or an iOS and a Mac version of an app. Or…
The point is that to target each platform with a high-quality application, it is necessary to create separate projects, each designed from the ground up for the target platform.
That said, when you're writing three or more versions of the same application, you will want to share a lot of code. All of the UI and UX of the application should be platform-specific, as will be a lot of the interaction with core operating system services. But a lot of the business logic, the "meat" that makes up your app, can hopefully be shared – implemented once, and used (maybe with minimal
#ifs), on all platforms.
That is where Elements RTL comes in.
Elements RTL is a library of base classes that compile for all target platforms (.NET, Cocoa, Java and Island) and provide you with an identical API to work with these classes on all platforms. For example, when you write code that uses a Elements RTL's
Dictionary class, this class will have the same methods and the same behavior on all platforms, so that the code you write against it, in turn, can be platform agnostic and compile for all platforms as well.
The Elements RTL library is not vast, but it does provide the key ingredients for being able to write a lot of platform-agnostic business logic code. It includes support for Lists and Dictionaries, numerical conversions, XML and Json parsing and writing, working with dates and times, string encodings, locales, HTTP requests, access to the system environment, and more.
Using Elements RTL also provides a consistent string type across all platforms, including support for automatically treating string literals and the C#
string keyword as a
The way Elements RTL is implemented is quite nifty, and could only have been done in Elements: Elements RTL uses a unique language feature called Mapped Types for a lot of its implementation.
What this does is taking existing classes provided by the underlying framework and making them available as new classes, under a different name and with different members. So rather than reinventing the wheel and implementing its own versions of exiting functionality, Sugar (mostly) takes existing framework classes and just exposes them to you using a common API.
For example, all four target platforms already have a sophisticated dictionary collection class:
java.util.HashMap<T,U>on Java and
These classes perform the same function, but they look nothing alike, so code written against any one of them would be platform-specific and not portable.
Elements RTL exposes each of these classes under the
RemObjects.Elements.RTL.Dictionary<T,U> name, and with the same well-defined API on each platform. This allows you to write code against the Sugar version of the Dictionary class, and that code will be portable and compile for all four platforms.
The Elements RTL projection of the type not only unifies the names of methods, such as
ClearAll, etc. but also the usage semantics of the class – for example how
nil values are handled (setting nil for a value removes it from the dictionary), or how the collection behaves when accessing unknown keys (it will return
Under the hood, the compiler does all the heavy lifting via its Mapped Types feature, so that your compiled code will actually end up using the underlying framework class –
RemObjects.Elements.RTL.Dictionar<T,U> won't even exist in the finished executable.
There are several upsides to this approach. For one, it saves Elements RTL from having to re-implement (and re-test) existing, well-proven framework classes. For another, it allows for Elements RTL classes to be toll-free cast-able to their underlying framework classes, if needed. For example, you might want to pass a Elements RTL Dictionary generated by your business code into a platform-specific part of your application – and that part can just use the class directly as, say, an NSDictionary, without any costly conversion. Because under the hood, at runtime, it is an NSDictionary.
Of course the Dictionary class is just one example of many. Elements RTL uses Mapped Types wherever possible, but also introduces some "regular" classes, where sensible, such as in areas where no proper reusable classes exist on one or more platforms. For example,
RemObjects.Elements.RTL.HTTP is a regular class that provides services for retrieving data from the network in various forms.
XmlDocument is also implemented in pure Elements code, cross-platform.
In fact, if you look at the source for
RemObjects.Elements.RTL.XmlDocument, you can see the power of Elements RTL itself in action, as the set of classes is implemented as pure cross-platform code on top of other Elements RTL types.
The Elements RTL library covers a variety of areas, and continues to grow over time – partly based on your feedback and contributions, and on your real world needs.
In fact, Elements RTL has been vastly expanded and improved with the latest Elements 9 release.
Let us know what you think, what you are missing or – even better – get involved by forking Elements RTL on GitHub and sending us pull requests.
Remember that Elements RTL is an optional feature. We pride ourselves for Elements targeting the native frameworks on each platform, and you will write a lot of great code with Elements that just uses those frameworks directly – same as you might right now be doing in C#, Java or Objective-C.
Elements RTL is not meant to abstract you away or protect you from the underlying frameworks, or to save you from having to learn the basic concepts of how these frameworks function and should be used from your applications. As such, its scope is a lot smaller than many other "cross-platform libraries" (or in fact as platform-specific abstraction libraries, such as the Delphi VCL).
Elements RTL is there to help you abstract those pieces of code that you want to share between platforms. It provides, by very definition, a compromise of an API that works on all four target platforms, but may not always feel native on all of them – platform conventions are too different to have a class with methods that "feel 100% right" on .NET, Java and Cocoa at the same time.
Elements RTL is an open source project, and driven as much by our internal work as it is by contributions from the community of Oxygene, RemObjects C# and Silver users. Let us know what functionality you are missing, or maybe even consider contributing some classes yourself. Pull requests are always welcome.
As of Elements 8, you can contribute to and work on the Elements RTL project in VisualStudio or Fire, without needing an Oxygene license.
A pre-compiled snapshot of Elements RTL ships in-the-box with Elements, so you simply need to add a reference to use it.
Elements RTL is an open source project; you can contribute on GitHub.
Elements RTL supersedes and replaces Sugar, our previous cross-platform library. Elements RTL evolved from Sugar, and is similar enough that existing projects that use Sugar can be switched over easily; but it is also different enough to warrant the new name.
Here are a few examples of where we at RemObjects use Elements RTL ourselves:
Fire/Water: Fire was originally written against the Cocoa APIs. It is a pretty vast codebase, but within a couple of months, we refactored all its non-UI internals to use Elements RTL instead – with the end result that the vast majority of code can now be shared with Water, its Windows version
EBuild: Our upcoming build chain for Elements 10 is being written from the ground up on Elements RTL. As a result, it can be compiled for .NET (which is where it will mainly be used), but also for native Cocoa (for embedding some of its core logic within Fire). As we work on EBuild, we almost forget we're writing cross-platform code, we just write Elements code, and it works everywhere.
CodeGen4: Our open source code generation library is written entirely in cross-platform Swift, on top of Elements RTL. It is used extensively in Fire/Water, Visual Studio, Data Abstract and elsewhere.
Remoting SDK CodeGen, built on top of CodeGen4 is also using Elements RTL in order to compile for .NET, as well as native Windows and Cocoa code for embedding in various places, again including Fire, Delphi, Service Builder, Service Importer for Mac, the
rodl2code command line tool, and more.
Elements RTL itself: A lot of the classes that are natively implemented in Elements RTL, such as
XmlDocument and the like, are written entirely or almost entirely in platform agnostic code, thanks to the lower levels of the RTL providing the abstraction.