SML# Document Version 4.0.0
19 Expressions

19.21 Static import expression: _import string : cfunty

This expression allows you to use C functions as SML# functions. The meaning of each component is as follows:

  • string: the name of the C function. This is the name that linker recognizes as an external symbol name.

  • cfunty: the type of the C function. It must be of the following form.

C function type: cfunty
cfunty ::= (cfunattr)?  argTyList -> retTyOpt
argTyList ::= ( argTy,,argTy (,varArgs)? ) (multiple arguments)
 | argTy (only one argument)
 | () (no argument)
retTyOpt ::= retTy
 | () (void type in C)
callback function type: argfunty
argfunty ::= (cfunattr)?  retTylist -> argTyOpt
retTyList ::= ( retTy,,retTy (,varRets)? ) (multiple arguments)
 | retTy (only one argument)
 | () (no argument)
argTyOpt ::= argTy
 | () (void type in C)
interoperable type: interoperableTy
interoperableTy ::= (tySeq)? longTycon (interoperable types only. See below for details)
argument type from SML# to C: argTy
argTy ::= argTy * * argTy (types of pointers to a structure)
 | { argTyRow } (types of pointers to a structure)
 | tyvar (boxed kind only)
 | interoperableTy
 | argfunty (callback function argument types)
argTyRow ::= lab : argTy (, argTyRow)? (lab must begin with decimal)
return type from C to SML#: retTy
retTy ::= interoperableTy
 | tyvar (boxed kind only)
variable-length argument type specification: varArgs and varRets
varArgs ::= ... ( argTy,,argTy )
varRets ::= ... ( retTy,,retTy )
C function attributes: cfunattr
cfunattr ::= __attribute__((attr,,attr))
att ::= cdecl  | stdcall  | fastcc  | pure  | fast

cfunty indicates the type of the C function in SML#’s type names and type notation. interoperableTy, the type names for C functions, must satisfy both of the following:

  1. 1.

    interoperableTyは以下のいずれかでなければならない.

    • Interoperable atomic types: int, int8, int16, int64, word, word8, word16, word64, real, real32, char, or string.

    • The types of C pointers: codeptr, interoperableTy ptr, or unit ptr.

    • The types of C pointers: tyvar ptr (ただしtyvar must be of either boxed or unboxed kind).

    • The types of size: ty size.

    • Array types: interoperableTy array, interoperableTy vector, or interoperableTy ref.

    • Polymorphic array types: tyvar array, tyvar vector, or tyvar ref (ただしtyvar must be of either boxed or unboxed kind).

    • An alias of one of the above types defined by a type declaration. (tySeq)? longTycon must be expanded to one of the above types. If an alias type occurs as an interoperableTy in the context of argTy, (tySeq)? longTycon may be expanded to an tuple or record type that can be regarded as an argTy.

  2. 2.

    Neither string, array, vector, nor ref may occur as the type of values that would be passed from C to SML# or be overwritten by a C function. In other words, these types must not occur as

    • interoperableTy in the context of retTy, and

    • the type parameter of array, ref, and ptr type.

以上の条件を満たすinteroperableTyは, その型名から自然に類推されるCの型に相当する. 対応を以下に示す.

interoperableTy 対応するCの型
int and its family signed integer of the same size
word and its family unsigned integer of the same size
real double
real32 float
char char
string const char *
codeptr pointer to a function
τ ptr pointer to τ
unit ptr void * or pointer to an incomplete type
τ size size_t
τ array pointer to the beginning of an array of τ
τ vector pointer to the beginning of a vector of τ
τ ref pointer to an one-element array of τ

Note that the size of int and word is always 32 bits. In almost of all modern operating systems, SML#’s int is identical to C’s int, whereas they are not identical in some systems whose int is not 32 bits.

argTy1 * * argTyn and {lab1:argTy1, , labn:argTyn} of argTy corresponds to the type of pointers to a const structure whose members are of type argTy1, , argTyn in the order of decimal of labels. If all argTyi are identical, it also corresponds to a pointer to the beginning of an const array of n elements of argTyi.

If and only if a C function acts like a parametric polymorphic function from the perspective of SML# programs, it is allowed to use type variables as a C function’s argument or return type. For example, an identical function in C

    void *id(void *x) { return x; }

is allowed to be imported like this:

    val ’a#boxed id = _import "id" : ’a -> ’a

Another example is printf function that prints an arbitrary pointer value.

    val ’a#boxed printPtr = _import "printf" : (string,...(’a)) -> int

The following C function attributes are available:

cdecl

The C function follows the standard calling convention of C functions on the target platform. This is the default if no calling convention is specified through function attributes.

stdcall

The C function follows stdcall calling convention on Windows platforms.

fastcc

The C function follows fastcc calling convention provided by LLVM.

pure

The C function is pure in the sense of SML#. In other words, C functions of this attribute does not perform any memory update and I/O, and its return value is decided only from the list of arguments. This attribute affects the optimization of the SML# compiler.

fast

The C function returns very quickly. It neither execute SML# code through callbacks nor pause the thread execution. The SML# compiler generates efficient invocation code for such functions. Note that, if a C function of this attribute either consumes much time or pause a thread execution, garbage collection would be suspended and consequently all threads would be suspended.

The type of this expression is the SML# function type corresponding to the type specified in cfunty. The correspondence is defined as follows.

C function type SML# function type
( argTy1, , argTyn (varArgs)? ) -> retTy argTy1 * * argTyn (* varArgs)? -> retTy

() in the argument or return type appear as unit in the SML# type. interoperableTy, tyvar, and * appear in the SML# type without modification. argfunty is interpreted similarly.

The value of this expression is the SML# function that calls the C function specified in string. As long as the C function type specification is correct, this function can be used similarly to ordinary SML# functions.