CSML is a development tool for the community of OCaml developers under Windows. It lets you write applications that freely mix OCaml and .NET code.
It can be used in the following scenarios:
-
Using .NET libraries (such as Winforms) from applications written in OCaml.
-
Providing a .NET API to OCaml components.
-
Developing mixed applications, where some parts are implemented in OCaml and other parts in .NET.
CSML is based on an Interface Definition Language to declare bi-directional bindings between OCaml and .NET. Scripts in this IDL specify both "pseudo-OCaml signatures" where each member is connected to a .NET component and "pseudo-C# signatures" where each member is connected to an OCaml component. This means that the user is in charge of organizing the bindings as they see fit. In particular, it is possible to choose custom names for imported components and to organize them into classes or namespaces in .NET and classes or modules in OCaml.
See the CSML spec for the "getting started" or "winforms" examples.
From such scripts, the CSML compiler generates C# and OCaml code to be compiled and linked separately. This code exposes components from one runtime to the other one (technically, this goes to the low-level FFI that both system provide with C). The main program is always in .NET and initializes the OCaml engine explicitly before calling OCaml components (which can then call back into .NET).
CSML takes care of all the low-level details of the bindings. In particular it takes care of making sure the two runtime systems work happily together (memory management, in-memory layout of objects, translation of values). Basic types (int, string, etc) and built-in structural types (lists, arrays, options, functions) are understood directly by CSML. Complex types can be transmitted by reference (as opaque pointers from one heap to the other one) or by an automatic structural mapping (OCaml datatypes translated to .NET classes).
First-class functions (in OCaml) and delegates (in .NET) are considered seriously in CSML. The system relies on predefined .NET generic delegates to mimic the structural aspect of OCaml arrow types. A .NET delegate is wrapped into an OCaml closure when it enters the OCaml world. Similarly, an OCaml closure is wrapped into a .NET delegate when it goes to the C# world; if this delegate is later sent back to OCaml, it is unwrapped to retrieve the original closure instead of being wrapped again.
Exceptions raised in one language are wrapped in the other language as regular exceptions, and round-tripping is supported (e.g. a C# exception that escapes to OCaml and then back to C# will retain all the information from the original one).
The interface generated by CSML does not compromise static type-safety as provided by each language. If the binding script is ill-typed on either side, this will be detected at compilation time.
-
A native port of OCaml under Windows. The current version has been tested with the MSVC 32-bit and 64-bit ports of OCaml 4.03, but two MinGW ports should work as well (perhaps with minor adjustments to the build system).
-
The Microsoft .NET framework. The current version has been tested with the version 3.5 of the framework, but CSML was initially developped against version 2.0.
-
Alternatively, CSML has been tested under Linux with Mono 4.x, but not used in production.
-
Moreover, it is expected that CSML could be made to work with little effort with the newest .NET Core framework both under Windows and other systems.
The root Makefile in the distribution has a default target "all" that builds the CSML compiler and runtime support. There is currently no support for "installing" the resulting assets.
This repository contains a few sample applications:
-
getting_started: show the basics of using CSML.
-
opaque_binding: abstract binding .NET <-> OCaml (values are not copied but transmitted by reference).
-
structured_mapping: concrete mapping of structured OCaml values (.NET classes are generated from OCaml type definitions).
-
winforms: a sample Windows Forms GUI application implemented in OCaml; illustrate importing .NET components as OCaml objects.
-
excel: expose OCaml function to Excel VBA (going through .NET and COM).
Look at this Makefile to get an idea of how to compile and link applications built with CSML.
CSML has been created by LexiFi and used in production since 2007, initially purely as an internal tool. It has been first released to the community in 2008, but only the runtime support was open-source at that time (the binding compiler was distributed in binary form). In 2016, LexiFi decided to switch to a full open-source model for CSML with an MIT license for the entire system.
Even though LexiFi only maintain CSML but does not put active development resources into it these days, we are happy to receive feedback, enhancement proposals or simply discuss future evolutions and potential uses of the tool.
CSML is currently available as "technology preview" only. No stable public release have been created.
Contact: alain.frisch@lexifi.com