_Ffiapply special form
This is a low level syntax for calling a C function. It has the following syntax.
_ffiapply <exp> (<arg>, ..., <arg>) : <ty>
- <exp> is an expression of type unit ptr denoting a C function pointer.
- <arg> is an argument to the C function.
- <ty> is the return type.
Arguments to C function can be given using the following syntax.
<arg> ::= <exp> : <ty> | _sizeof(<ty>)
- <exp> : <ty> is an argument expression and its type.
- _sizeof(<ty>) is a reference to the size attribute of the type ty which the SML# type-directed compiler maintain. This special form is automatically substituted with the term that denotes the size of the type.
- <ty> can be any interoperable type.
A C library function qsort(3 can be called as follows.
val libc = DynamicLink.dlopen "/lib/libc.so.6" val c_qsort = DynamicLink.dlsym (libc, "qsort") fun qsort (a, f) = _ffiapply c_qsort (a : 'a array, Array.length a : int, _sizeof('a), f : ('a ptr, 'a ptr) -> int) : unit
qsort has two arguments: an array a and a callback function f. In the function body, it passes the size of the data element through the special term _sizeof('a) to the C function. This allows the C function to traverse the array by advancing the pointer. The above code yields the following expected declaration.
val qsort : ['a. 'a array * ('a ptr * 'a ptr -> int) -> unit]
Conceptually, _ffiapply construct can be understood as an inlined typed intermediate code that is to be plugged-in the intermediate code, SML# type-directed compiler generates. No static typechecking is performed for this construct. Therefore, a special care must be taken to ensure that the number and the types of arguments agree with those of C function.
As far as these two conditions are met, the rest of the system is guaranteed to be type safe. This allow type safe usage of low-level efficient polymorphic code such qsort above as a typed polymorphic function in SML# program.