6.4  Callbacks

To enable an external C function to call back to Scheme, the form foreign-callback-lambda (or foreign-callback-lambda*) has to be used. This generates special code to save and restore important state information during execution of C code. There are two ways of calling Scheme procedures from C: the first is to invoke the runtime function C_callback with the closure to be called and the number of arguments. The second is to define an externally visible wrapper function around a Scheme procedure with the define-external or foreign-callback-wrapper forms.

Note: the names of all functions, variables and macros exported by the Chicken runtime system start with ``C_''. It is advisable to use a different naming scheme for your own code to avoid name clashes. Callbacks (either defined by define-external or foreign-callback-wrapper do not capture the lexical environment.

[syntax] (define-external [QUALIFIERS] (NAME (ARGUMENTTYPE1 VARIABLE1) ...) RETURNTYPE BODY ...)
[syntax] (define-external NAME TYPE [INIT])
The first form defines an externally callable Scheme procedure. NAME should be a symbol, which, when converted to a string, represents a legal C identifier. ARGUMENTTYPE1 ... and RETURNTYPE are foreign type specifiers for the argument variables VAR1 ... and the result, respectively. QUALIFIERS is an optional qualifier for the foreign procedure definition, like __stdcall.

(define-external (foo (c-string x)) int (string-length x))

is equivalent to

(define foo 
  (foreign-callback-wrapper int "foo" 
    (c-string) (lambda (x) (string-length x))))

The second form of define-external can be used to define variables that are accessible from foreign code. It declares a global variable named by the symbol NAME that has the type TYPE. INIT can be an arbitrary expression that is used to initialize the variable. NAME is accessible from Scheme just like any other foreign variable defined by define-foreign-variable.

(define-external foo int 42)
((foreign-lambda* int ()
  "return(foo);"))           ==> 42

Note: don't be tempted to assign strings or bytevectors to external variables. Garbage collection moves those objects around, so it is very bad idea to assign pointers to heap-data. If you have to do so, then copy the data object into statically allocated memory (for example by using object-evict).

[syntax] (foreign-callback-wrapper RETURNTYPE NAME [QUALIFIERS] (ARGUMENTTYPE1 ...) EXP)
Defines an externally callable wrapper around the procedure EXP. EXP must be a lambda expression of the form (lambda ...). The wrapper will have the name NAME and will have a signature as specified in the return- and argument-types given in RETURNTYPE and ARGUMENTTYPE1 .... QUALIFIERS is a qualifier string for the function definition (see define-external).

[C function] C_word C_callback(C_word closure, int argc)
This function can be used to invoke the Scheme procedure closure. argc should contain the number of arguments that are passed to the procedure on the temporary stack. Values are put onto the temporary stack with the C_save macro.