On this page:
_  cprocedure
_  fun
function-ptr
->
3.6.1 Custom Function Types
define-fun-syntax
_  ?
_  ptr
_  box
_  list
_  vector
_  bytes
_  bytes/  nul-terminated

3.6 Function Types 🔗

procedure

(_cprocedure input-types    
  output-type    
  [#:abi abi    
  #:varargs-after varargs-after    
  #:atomic? atomic?    
  #:async-apply async-apply    
  #:lock-name lock-name    
  #:in-original-place? in-original-place?    
  #:blocking? blocking?    
  #:callback-exns? callback-exns?    
  #:save-errno save-errno    
  #:wrapper wrapper    
  #:keep keep])  any
  input-types : (list ctype?)
  output-type : ctype?
  abi : (or/c #f 'default 'stdcall 'sysv) = #f
  varargs-after : (or/c #f positive-exact-integer?) = #f
  atomic? : any/c = #f
  async-apply : (or/c #f ((-> any/c) . -> . any/c) box?) = #f
  lock-name : (or/c string? #f) = #f
  in-original-place? : any/c = #f
  blocking? : any/c = #f
  callback-exns? : any/c = #f
  save-errno : (or/c #f 'posix 'windows) = #f
  wrapper : (or/c #f (procedure? . -> . procedure?)) = #f
  keep : (or/c boolean? box? (any/c . -> . any/c)) = #t
A type constructor that creates a new function type, which is specified by the given input-types list and output-type. Usually, the _fun syntax (described below) should be used instead, since it manages a wide range of complicated cases and may enable static code generation.

The resulting type can be used to reference foreign functions (usually ffi-objs, but any pointer object can be referenced with this type), generating a matching foreign callout object. Such objects are new primitive procedure objects that can be used like any other Racket procedure. As with other pointer types, #f is treated as a NULL function pointer and vice versa.

A type created with _cprocedure can also be used for passing Racket procedures to foreign functions, which will generate a foreign function pointer that calls to the given Racket callback procedure. There are no restrictions on the representation of the Racket procedure; in particular, the procedure can have free variables that refer to bindings in its environment. Callbacks are subject to run-time constraints, however, such as running in atomic mode or not raising exceptions; see more information on callbacks below.

The optional abi keyword argument determines the foreign ABI that is used. Supplying #f or 'default indicates the platform-dependent default. The other possible values—'stdcall and 'sysv (i.e., “cdecl”)—are currently supported only for 32-bit Windows; using them on other platforms raises an exception. See also ffi/winapi.

The optional varargs-after argument indicates whether some function-type arguments should be considered “varargs,” which are argument represented by an ellipsis ... in the C declaration (but by explicit arguments in input-types). A #f value indicates that the C function type does not have varargs. If varargs-after is a number, then arguments after the first varargs-after arguments in input-types are varargs. Note that #f is different from (length input-types) on some platforms; the possibility of varargs for a function may imply a different calling convention even for non-vararg arguments. Note also that a non-#f varargs-after does not mean that you can supply any number of arguments to a callout or receive any number of arguments to a callback using the procedure type; to work with different argument counts and argument types, use _cprocedure (or _fun) separately for each combination.

For callouts to foreign functions with the generated type:

For callbacks to Racket functions with the generated type:

Changed in version 6.3 of package base: Added the #:lock-name argument.
Changed in version 6.12.0.2: Added the #:blocking? argument.
Changed in version 7.9.0.16: Added the #:varargs-after argument.
Changed in version 8.0.0.8: Added the #:callback-exns? argument.

syntax

(_fun fun-option ... maybe-args type-spec ... -> type-spec
      maybe-wrapper)
 
fun-option = #:abi abi-expr
  | #:varargs-after varargs-after-expr
  | #:save-errno save-errno-expr
  | #:keep keep-expr
  | #:atomic? atomic?-expr
  | #:async-apply async-apply-expr
  | #:lock-name lock-name-expr
  | #:in-original-place? in-original-place?-expr
  | #:blocking? blocking?-expr
  | #:callback-exns? callback-exns?-expr
  | #:retry (retry-id [arg-id init-expr])
     
maybe-args = 
  | formals ::
     
type-spec = type-expr
  | (id : type-expr)
  | (type-expr = value-expr)
  | (id : type-expr = value-expr)
     
maybe-wrapper = 
  | -> output-expr
Creates a new function type. The _fun form is a convenient syntax for the _cprocedure type constructor, and it can enable more static generation of callout and callback code; see _fun from ffi/unsafe/static for more information.

In the simplest form of _fun, only the input type-exprs and the output type-expr are specified, and each types is a simple expression, which creates a straightforward function type. For example,

(_fun _string _int -> _int)

specifies a function that receives a string and an integer and returns an integer.

See _cprocedure for information about the #:abi, #:varargs-after, #:save-errno, #:keep, #:atomic?, #:async-apply, #:in-original-place?, #:blocking, and #:callback-exns? options.

In its full form, the _fun syntax provides an IDL-like language that creates a wrapper function around the primitive foreign function when the type is used for a callout. These wrappers can implement complex interfaces given simple specifications:
  • The full form of each argument type-spec can include an optional label and an expression. A label id : makes the argument value accessible to later expressions using id. A = value-expr expression causes the wrapper function to calculates the argument for that position using value-expr, implying that the wrapper does not expect to be given an argument for that position.

    For example,

    (_fun (s : _string) (_int = (string-length s)) -> _int)

    produces a wrapper that takes a single string argument and calls a foreign function that takes a string and an integer; the string’s length is provided as the integer argument.

  • If the optional output-expr is specified, or if an expression is provided for the output type, then the expression specifies an expression that will be used as a return value for the function call, replacing the foreign function’s result. The output-expr can use any of the previous labels, including a label given for the output to access the foreign function’s return value.

    For example,

    (_fun _string (len : _int) -> (r : _int) -> (min r len))

    produces a wrapper that returns the minimum of the foreign function’s result and the given integer argument.

  • A #:retry (retry-id [arg-id init-expr] ...) specification binds retry-id for use in an output-expr for retrying the foreign call (normally in tail position). The function bound to retry-id accepts each arg-id as an argument, each arg-id can be used in = value-exprs, and each init-exprs provides the initial value for the corresponding arg-id.

    For example,

    (_fun #:retry (again [count 0])
          _string _int -> (r : _int)
          -> (if (and (= r ERR_BUSY)
                      (< count 5))
                 (again (add1 count))
                 r))

    produces a wrapper that calls the foreign function up to five times if it continues to produce a number equal to ERR_BUSY.

  • In rare cases where complete control over the input arguments is needed, the wrapper’s argument list can be specified as maybe-args with a formals as for lambda (including keyword arguments and/or a “rest” argument). When an argument type-spec includes a label that matches an binding identifier in formals, then the identifier is used as the default value for the argument. All argument type-specs must include either explicit = value-expr annotations or an implicit one through a matching label.

    For example,

    (_fun (n s) :: (s : _string) (n : _int) -> _int)

    produces a wrapper that receives an integer and a string, but the foreign function receives the string first.

Changed in version 6.2 of package base: Added the #:retry option.
Changed in version 6.3: Added the #:lock-name option.
Changed in version 6.12.0.2: Added the #:blocking? option.
Changed in version 7.9.0.16: Added the #:varargs-after option.
Changed in version 8.0.0.8: Added the #:callback-exns? option.

procedure

(function-ptr ptr-or-proc fun-type)  cpointer?

  ptr-or-proc : (or cpointer? procedure?)
  fun-type : ctype?
Casts ptr-or-proc to a function pointer of type fun-type.

syntax

->

A literal used in _fun forms. (It’s unfortunate that this literal has the same name as -> from racket/contract, but it’s a different binding.)

3.6.1 Custom Function Types 🔗

The behavior of the _fun type can be customized via custom function types, which are pieces of syntax that can behave as C types and C type constructors, but they can interact with function calls in several ways that are not possible otherwise. When the _fun form is expanded, it tries to expand each of the given type expressions, and ones that expand to certain keyword-value lists interact with the generation of the foreign function wrapper. This expansion makes it possible to construct a single wrapper function, avoiding the costs involved in compositions of higher-order functions.

Custom function types are macros that expand to a sequence (key: val ...), where each key: is from a short list of known keys. Each key interacts with generated wrapper functions in a different way, which affects how its corresponding argument is treated:

The pre: and post: bindings can be of the form (id => expr) to use the existing value. Note that if the pre: expression is not (id => expr), then it means that there is no input for this argument to the _fun-generated procedure. Also note that if a custom type is used as an output type of a function, then only the post: code is used.

Most custom types are meaningful only in a _fun context, and will raise a syntax error if used elsewhere. A few such types can be used in non-_fun contexts: types which use only type:, pre:, post:, and no others. Such custom types can be used outside a _fun by expanding them into a usage of make-ctype, using other keywords makes this impossible, because it means that the type has specific interaction with a function call.

syntax

(define-fun-syntax id transformer-expr)

Binds id as a custom function type as well as a syntax transformer (i.e, macro). The type is expanded by applying the procedure produced by transformer-expr to a use of the custom function type.

For instance, the following defines a new type that automatically coerces the input number to an inexact form which is compatible with the _float type.

(define-fun-syntax _float*
  (syntax-id-rules (_float*)
    [_float* (type: _float pre: (x => (+ 0.0 x)))]))
 
(_fun _float* -> _bool)

syntax

_?

A custom function type that is a marker for expressions that should not be sent to the foreign function. Use this to bind local values in a computation that is part of an ffi wrapper interface, or to specify wrapper arguments that are not sent to the foreign function (e.g., an argument that is used for processing the foreign output).

Examples:

(_fun _? ; not sent to foreign function
      _int -> _int)
(_fun [init : _?] ; init is used for pre-processing
      [boxed : (_box _int) = (box init)]
      -> _void)
(_fun [offset : _?] ; offset is used for post-processing
      -> [res : _int]
      -> (+ res offset))

syntax

(_ptr mode type-expr maybe-malloc-mode)

 
mode = i
  | o
  | io
     
maybe-malloc-mode = 
  | #f
  | raw
  | atomic
  | nonatomic
  | tagged
  | atomic-interior
  | interior
  | stubborn
  | uncollectable
  | eternal
Creates a C pointer type, where mode indicates input or output pointers (or both). The mode can be one of the following (matched as a symbol independent of binding):

For example, the _ptr type can be used in output mode to create a foreign function wrapper that returns more than a single argument. The following type:

(_fun (i : (_ptr o _int))
      -> (d : _double)
      -> (values d i))

creates a function that calls the foreign function with a fresh integer pointer, and use the value that is placed there as a second return value.

The pointer argument created by _ptr is allocated using allocated using (malloc type-expr) if maybe-malloc-mode is not specified or if it is #f, (malloc type-expr 'maybe-malloc-mode) otherwise.

Changed in version 7.7.0.6 of package base: The modes i, o, and io match as symbols instead of free identifiers.
Changed in version 8.0.0.13: Added malloc-mode.

syntax

(_box type maybe-malloc-mode)

A custom function type similar to a (_ptr io type) argument, where the input is expected to be a box holding an appropriate value, which is unboxed on entry and modified accordingly on exit. The optional maybe-malloc-mode is the same as for _ptr.

Example:

(_fun (_box _int) -> _void)
(_fun [boxed : (_box _int) = (box 0)]
      -> [res : _int]
      -> (values res (unbox boxed)))

syntax

(_list mode type maybe-len maybe-mode)

 
mode = i
  | o
  | io
     
maybe-len = 
  | len-expr
     
maybe-mode = 
  | atomic
  | raw
  | atomic
  | nonatomic
  | tagged
  | atomic-interior
  | interior
  | stubborn
  | uncollectable
  | eternal
A custom function type that is similar to _ptr, except that it is used for converting lists to/from C vectors. The optional maybe-len argument is needed for output values where it is used in the post code, and in the pre code of an output mode to allocate the block. (If the length is 0, then NULL is passed in and an empty list is returned.) In either case, it can refer to a previous binding for the length of the list which the C function will most likely require. The maybe-mode, if provided, is quoted and passed to malloc as needed to allocate the C representation.

For example, the following type corresponds to a function that takes a vector argument of type *float (from a Racket list input) and a length argument of type int for the vector:

(_fun [vec : (_list i _float)]
      ; this argument is implicitly provided
      [_int = (length vec)]
      -> _void)

In this next example, the type specifies a function that provides output through a given output vector (represented as a list on the Racket side) and through a boolean return value. The FFI-bound function will take an integer argument and return two values, the vector and the boolean.

(_fun [len : _int]
      [vec : (_list o _float len)]
      -> [res : _bool]
      -> (values vec res))

Changed in version 7.7.0.2 of package base: Added maybe-mode.

#:changed "7.7.0.6" The modes i, o, and io match as symbols instead of free identifiers.]

syntax

(_vector mode type maybe-len maybe-mode)

A custom function type like _list, except that it uses Racket vectors instead of lists.

Examples:

(_fun [vec : (_vector i _float)]
      [_int = (length vec)]
      -> _void)
(_fun [len : _int]
      [vec : (_vector o _float len)]
      -> [res : _bool]
      -> (values vec res))

See _list for more explanation about the examples.

Changed in version 7.7.0.2 of package base: Added maybe-mode.
Changed in version 7.7.0.6: The modes i, o, and io match as symbols instead of free identifiers.

syntax

_bytes

(_bytes o len-expr)
The _bytes form by itself corresponds to C’s char* type; a byte string is passed as _bytes without any copying. Beware that a Racket byte string is not necessarily nul terminated; see also _bytes/nul-terminated.

In the BC implementation of Racket, a C non-NULL result value is converted to a Racket byte string without copying; the pointer is treated as potentially managed by the garbage collector (see _gcpointer for caveats). In the CS implementation of Racket, conversion requires copying to represent a C char* result as a Racket byte string, and the original pointer is not treated as managed by the garbage collector. In both cases, the C result must have a nul terminator to determine the Racket byte string’s length.

A (_bytes o len-expr) form is a custom function type. As an argument, a byte string is allocated with the given length; in the BC implementation, that byte string includes an extra byte for the nul terminator, and (_bytes o len-expr) as a result wraps a C non-NULL char* pointer as a byte string of the given length. For the CS implementation, the allocated argument does not include a nul terminator and a copy is made for a result string.

As usual, _bytes treats #f as NULL and vice versa. As a result type, (_bytes o len-expr) works only for non-NULL results.

The _bytes/nul-terminated type is like _bytes, but an explicit nul-terminator byte is added to a byte-string argument, which implies copying. As a result type, a char* is copied to a fresh byte string (without an explicit nul terminator).

When (_bytes/nul-terminated o len-expr) is used as an argument type, a byte string of length len-expr is allocated. Similarly, when (_bytes/nul-terminated o len-expr) is used as a result type, a char* result is copied to a fresh byte string of length len-expr.

As usual, _bytes/nul-terminated treats #f as NULL and vice versa. As a result type, (_bytes/nul-terminated o len-expr) works only for non-NULL results.

Added in version 6.12.0.2 of package base.