1 Introduction

The extension of Haskell 98 defined in this report facilitates the use of non-Haskell code from Haskell and vice versa in a portable manner. Intrusion into Haskell 98 has been kept to a minimum and the defined facilities have been extensively tested with large libraries.

The present Version 1.0 of the FFI report does only fully specify the interaction between Haskell code with code that follows the C calling convention. However, the design of the FFI is such that it enables the modular extension of the present definition to include the calling conventions of other programming languages, such as C++ and Java. A precise definition of the support for those languages is expected to be included in later versions of this report. The second major omission from the present report is the definition of the interaction with multithreading in the foreign language and, in particular, the treatment of thread-local state. Work on this problem is not sufficiently mature to be included into Version 1.0 of the report.

1.1 Embedding Into Haskell 98

The present report is to be regarded as an addendum to the Haskell 98 Report [7]. As such, syntactic and semantic definitions refer to names and definitions in the Haskell 98 Report where appropriate without further explanation. Care has been taken to invalidate as few as possible legal Haskell 98 programs in the process of adding FFI support. In particular, only a single addition to the set of reserved identifiers, namely foreign, has been made.

Moreover, it is expected that the present FFI specification will be considered for inclusion into future revisions of the Haskell standard.

1.2 Language-Specific FFI Support

The core of the present specification is independent of the foreign language that is used in conjunction with Haskell. However, there are two areas where FFI specifications must become language specific: (1) the specification of external names and (2) the marshalling of the basic types of a foreign language. As an example of the former, consider that in C [4] a simple identifier is sufficient to identify an object, while Java [2], in general, requires a qualified name in conjunction with argument and result types to resolve possible overloading. Regarding the second point, consider that many languages do not specify the exact representation of some basic types. For example the type int in C may be 16, 32, or 64 bits wide. Similarly, the Haskell report guarantees only that Int covers at least the range [-229,229 - 1]. As a consequence, to reliably represent values of C’s int in Haskell, we have to introduce a new type CInt, which is guaranteed to match the representation of int.

The specification of external names, dependent on a calling convention, is described in Section 4, whereas the marshalling of the basic types in dependence on a foreign language is described in Section 5.

1.3 Contexts

For a given Haskell system, we define the Haskell context to be the execution context of the abstract machine on which the Haskell system is based. This includes the heap, stacks, and the registers of the abstract machine and their mapping onto a concrete architecture. We call any other execution context an external context. Generally, we cannot assume any compatibility between the data formats and calling conventions between the Haskell context and a given external context, except where the Haskell 98 report explicitly prescribes a specific data format.

The principal goal of a foreign function interface is to provide a programmable interface between the Haskell context and external contexts. As a result Haskell threads can access data in external contexts and invoke functions that are executed in an external context as well as vice versa. In the rest of this report, external contexts are usually identified by a calling convention.

1.4 Cross Language Type Consistency

Given that many external languages support static types, the question arises whether the consistency of Haskell types with the types of the external language can be enforced for foreign functions. Unfortunately, this is, in general, not possible without a significant investment on the part of the implementor of the Haskell system (i.e., without implementing a dedicated type checker). For example, in the case of the C calling convention, the only other approach would be to generate a C prototype from the Haskell type and leave it to the C compiler to match this prototype with the prototype that is specified in a C header file for the imported function. However, the Haskell type is lacking some information that would be required to pursue this route. In particular, the Haskell type does not contain any information as to when const modifiers have to be emitted.

As a consequence, this report does not require the Haskell system to check consistency with foreign types. Nevertheless, Haskell systems are encouraged to provide any cross language consistency checks that can be implemented with reasonable effort.