Previous Contents Next
Chapter 17 Interfacing C with Objective Caml

This chapter describes how user-defined primitives, written in C, can be linked with Caml code and called from Caml functions.

17.1 Overview and compilation information

17.1.1 Declaring primitives

User primitives are declared in an implementation file or struct...end module expression using the external keyword:
        external name : type = C-function-name
This defines the value name name as a function with type type that executes by calling the given C function. For instance, here is how the input primitive is declared in the standard library module Pervasives:
        external input : in_channel -> string -> int -> int -> int
                       = "input"
Primitives with several arguments are always curried. The C function does not necessarily have the same name as the ML function.

External functions thus defined can be specified in interface files or sig...end signatures either as regular values
        val name : type
thus hiding their implementation as a C function, or explicitly as ``manifest'' external functions
        external name : type = C-function-name
The latter is slightly more efficient, as it allows clients of the module to call directly the C function instead of going through the corresponding Caml function.

The arity (number of arguments) of a primitive is automatically determined from its Caml type in the external declaration, by counting the number of function arrows in the type. For instance, input above has arity 4, and the input C function is called with four arguments. Similarly,
    external input2 : in_channel * string * int * int -> int = "input2"
has arity 1, and the input2 C function receives one argument (which is a quadruple of Caml values).

Type abbreviations are not expanded when determining the arity of a primitive. For instance,
        type int_endo = int -> int
        external f : int_endo -> int_endo = "f"
        external g : (int -> int) -> (int -> int) = "f"
f has arity 1, but g has arity 2. This allows a primitive to return a functional value (as in the f example above): just remember to name the functional return type in a type abbreviation.

17.1.2