On this page:
->
ffi2-procedure
ffi2-callback
define-ffi2-procedure
define-ffi2-definer
make-not-available
default_  abi
cdecl_  abi
stdcall_  abi
define-ffi2-abi
9.2.0.3

2.6 Foreign Procedures and Callbacks🔗ℹ

ffi2 type

(-> arg-or-do ...
    maybe-varargs
    result maybe-errno
    option
    ...)
 
arg-or-do = arg
  | #:do [defn-or-expr ...]
     
arg = type
  | [arg-id : type]
  | [type = auto-expr]
  | [arg-id : type = auto-expr]
     
maybe-varargs = 
  | #:varargs arg-or-do ...
     
result = result-type
  | [result-id : result-type]
     
maybe-errno = 
  | #:errno
  | #:get-last-error
  | [errno-id : #:errno]
  | [errno-id : #:get-last-error]
     
option = #:result result-expr
  | #:abi abi
  | #:atomic
  | #:collect-safe
  | #:allow-callback-exn
  | #:in-original
Describes the type of a procedure. The C representation of a procedure is an address, while the Racket representation is a Racket procedure.

The racket/contract library also provides ->. To avoid conflicts, consider renaming the racket/contract binding to ->/c on import.

A -> type is normally used with ffi2-procedure or define-ffi2-procedure to obtain a Racket produce that calls a C function. That use of -> creates a foreign callout.

A -> type can also be used with ffi2-callback to turn a Racket procedure into a function callback by C as represented by a pointer object. That of use of -> creates a foreign callback. A callback always runs in atomic mode, which means that it must not attempt any synchronization operations and generally must not raise an exception (unless #:allow-callback-exn is used for a callout that reaches the callback). If a callback is run in an operating-system thread that was not started by Racket, then the callback is subject to the same constraints as a procedure passed to call-in-os-thread.

Each arg describes a type for an argument, each with an optional name arg-id and an optional auto-expr. When an argument has an auto-expr, no corresponding argument is provided to a callout. Each auto-expr can refer to arg-ids for arguments without auto-exprs and to earlier arguments that have auto-exprs. When an arrow type is used for a foreign callback (instead of a callout), arg-ids and auto-exprs have no effect.

Each #:do form among the args inserts additional expressions and definitions that are evaluated similar to auto-exprs, that can refer to earlier argument names, to argument names without auto-exprs, and to definitions from earlier #:do forms. An auto-expr can also refer to definitions from preceding #:do forms.

A result can have a result-id. That identifier can be used (along with the arg-ids) in a result-expr supplied with #:result. The value of #:result becomes the result for a callout, and it is not used for a callback.

If #:errno or #:get-last-error (optionally with a errno-id) is specified after result-type, then calling a function produced by ffi2-procedure returns two values (absent a #:result expression): the foreign procedure’s return value and the value of the C library’s errno or the result of the GetLastError function on Windows. The errno or GetLastError result is obtained just after the foreign procedure call returns and before it can be changed. On platforms other than Windows, #:get-last-error is treated as #:errno. A #:errno or #:get-last-error specification has no effect for a callback. If errno-id is specified, it can be referenced in a result-expr to determine a callout result.

Each option affects the way a foreign procedure is called or how a callback is handled:

  • #:abi: Uses abi as the ABI for a foreign callout or foreign callback. See default_abi, cdecl_abi, and stdcall_abi.

  • #:atomic: Adjusts a foreign callout to potentially improve performance. The foreign procedure must not invoke any callbacks or otherwise reach the Racket run-time system, so it can be considered an atomic operation from the perspective of Racket. This option has no effect on foreign callbacks.

  • #:collect-safe: Adjusts a foreign callout to allow Racket garbage collection concurrent with the call, or adjusts a foreign callback to re-enable synchronization with the garbage collector during the callback (i.e., only collect-safe callbacks are allowed to be invoked via a collect-safe procedure call; a collect-safe callback can be invoked through a non-collect-safe foreign procedure call). Note that a collect-safe call makes sense only when arguments to the foreign procedure are not managed by the Racket garbage collector or are immobile and reliably retained.

  • #:allow-callback-exn: Adjusts a foreign callout so that a foreign callback is allowed to raise an exception that escape the foreign-procedure call. This option has no effect on foreign callbacks themselves. A foreign callback must never raise an exception unless it is invoked via foreign procedure call using this option.

  • #:in-original: Adjusts a foreign callout to run in a coroutine thread within Racket’s main place (which is useful if the foreign procedure is not thread-safe), or adjusts a foreign callback invocation so that it runs in a coroutine thread within the current place (which can be useful if the callback might otherwise run in a thread not created by Racket).In the BC variant of Racket, #:in-original is required if a callback may run in a thread not created by Racket. The callout or callback happens in the context of an unspecified Racket coroutine thread, so it must not raise an exception, and it is still in atomic mode. The callback blocks the original thread until it completes in a coroutine thread.

syntax

(ffi2-procedure ptr-expr arrow-type)

Creates a foreign callout. The arrow-type must be either an immediate -> type or a type name that is defined as an -> type.

Using ffi2-procedure is equivalent to (ffi2-cast ptr-expr #:from ptr_t #:to arrow-type) to convert a foreign function pointer to a procedure that can be called from Racket.

syntax

(ffi2-callback proc-expr arrow-type)

Creates a foreign callback. The arrow-type must be either an immediate -> type or a type name that is defined as an -> type.

Using ffi2-callback is equivalent to (ffi2-cast proc-expr #:from arrow-type #:to ptr_t) to convert a Racket procedure to a function pointer to be called in a foreign context.

A foreign callback is managed by the Racket garbage collector. A callback is always immobile in the sense of using ffi2-malloc in #:gcable-immobile mode, but the callback must be retained somehow as long as it is relevant for calls from a foreign context. A callback is automatically retained in that sense if it is passed to a foreign callout that uses the callback only until the callout returns.

syntax

(define-ffi2-procedure id arrow-type
  option ...)
 
option = #:lib lib-expr
  | #:c-id c-id
  | #:fail fail-expr
  | #:wrap wrap-expr
A convenience form for binding id as a foreign callout. The #:lib option must be provided, and an exported object with name c-id is found in the library produced by lib-expr. If c-id is not declared using #:c-id, then id is used.

If c-id (or id) is not exported from ffi-lib, then if fail-expr is called with 'id as its argument, and id is defined as that result instead of a callout based on arrow-type.

If wrap-expr is provided, then the value that otherwise would be bound to id is passed to the result of wrap-expr, and id is defined as the result of that call.

syntax

(define-ffi2-definer id
  option ...)
 
option = #:lib lib-expr
  | #:default-fail fail-expr
  | #:default-wrap wrap-expr
  | #:provide
Defines id as a definition form with the same syntax as define-ffi2-procedure, except that a definition using id cannot have a #:lib clause.

If #:default-fail or #:default-wrap are provided, they supply expressions that are used as #:fail or #:wrap defaults for id.

If #:provide is specified, then a name defined by id is also exported using provide with protect-out.

procedure

(make-not-available name)  procedure?

  name : symbol?
Returns a procedure that takes any number of arguments, including keyword arguments, and raises an exn:fail:unsupported exception from name. This function is intended for use with #:fail in define-ffi2-procedure or #:default-fail in define-ffi2-definer.

ffi2 abi

default_abi

ffi2 abi

cdecl_abi

ffi2 abi

stdcall_abi

syntax

(define-ffi2-abi name abi)

An ABI specifies a calling convention to use for a foreign procedure or callback. On most platforms, the only meaningful ABI is default_abi, because most platforms have only a single standard ABI for C procedures. Windows for 32-bit x86 defines multiple procedure ABIs, and cdecl_abi and stdcall_abi specify alternative ABIs for that platform; on other platforms, cdecl_abi and stdcall_abi are treated the same as default_abi.

Use define-ffi2-abi to define an alias for an ABI. The system-type-case form works as an ABI to support a platform-dependent choice.