Chicken » Module (chicken foreign)

## Module (chicken foreign)

This module provides a foreign function interface to access externally defined functions and variables in C-compatible languages, as well as operating-system specific functionality.

Note that this interface is source-based, since CHICKEN translates Scheme code to C. It is not binary, as in many other Scheme implementations.

Several special forms of this interface refer to foreign type specifies, consult the Foreign type specifies of this manual for more information.

## Accessing external objects

### foreign-code

`(foreign-code STRING ...)`syntax

  Executes the embedded C/C++ code `STRING ...`, which should be a sequence of C statements, which are executed and return an unspecified result.

      (foreign-code "doSomeInitStuff();")     =>  #<unspecified>

  Code wrapped inside `foreign-code` may not invoke callbacks into Scheme.

### foreign-value

`(foreign-value CODE TYPE)`syntax

  Evaluates the embedded C/C++ expression `CODE` (which may be a string or symbol), returning a value of type given in the foreign-type specifier `TYPE`.

      (print (foreign-value "my_version_string" c-string))

### foreign-declare

`(foreign-declare STRING ...)`syntax

  Include given strings verbatim into header of generated file.

### define-foreign-type

`(define-foreign-type NAME TYPE [ARGCONVERT [RETCONVERT]])`syntax

  Defines an alias for `TYPE` with the name `NAME` (a symbol). `TYPE` may be a type-specifier or a string naming a C type. The namespace of foreign type specifiers is separate from the normal Scheme namespace. The optional arguments `ARGCONVERT` and `RETCONVERT` should evaluate to procedures that map argument- and result-values to a value that can be transformed to `TYPE`:

      (define-foreign-type char-vector
        nonnull-c-string
        (compose list->string vector->list)
        (compose list->vector string->list) )

      (define strlen
        (foreign-lambda int "strlen" char-vector) )

      (strlen '#(#\a #\b #\c))                      ==> 3

      (define memset
        (foreign-lambda char-vector "memset" char-vector char int) )

      (memset '#(#_ #_ #_) #\X 3)                ==> #(#\X #\X #\X)

  Foreign type-definitions are only visible in the compilation-unit in which they are defined, so use `include` to use the same definitions in multiple files.

### foreign-type-size

`(foreign-type-size TYPE)`syntax

  Returns the size of the storage required to hold values of the given foreign type `TYPE`. This is basically equivalent to

      (foreign-value "sizeof(TYPE)" size_t)

  but also handles user-defined types and allows "TYPE" to be a string, which will be given literally to the `sizeof` operator.

### define-foreign-variable

`(define-foreign-variable NAME TYPE [STRING])`syntax

  Defines a foreign variable of name `NAME` (a symbol). `STRING` should be the real name of a foreign variable or parameterless macro. If `STRING` is not given, then the variable name `NAME` will be converted to a string and used instead. All references and assignments (via `set!`) are modified to correctly convert values between Scheme and C representation. This foreign variable can only be accessed in the current compilation unit, but the name can be lexically shadowed. Note that `STRING` can name an arbitrary C expression. If no assignments are performed, then `STRING` doesn't even have to specify an lvalue. See that `define-foreign-variable` will not generate C declarations or memory allocation code; use it to include references to variables in external C code. To actually create Scheme variables visible from C, use `define-external` (see the Manual section on Callbacks). For example, the following code:

      (import foreign)
      (define-foreign-variable x double "var_x")
      (print x)

  will not work, because a reference to `var_x` will be inserted in the C code, but no declaration will be included (this can be easily verified by translating the program into C with `csc -t program.scm`). Changing the second line to `(define-external x double 0.5)` will work (and the value 0.5 will be printed).

### foreign-lambda

`(foreign-lambda RETURNTYPE NAME ARGTYPE ...)`syntax

  Represents a binding to an external routine. This form can be used in the position of an ordinary `lambda` expression. `NAME` specifies the name of the external procedure and should be a string or a symbol.

### foreign-lambda*

`(foreign-lambda* RETURNTYPE ((ARGTYPE VARIABLE) ...) STRING ...)`syntax

  Similar to `foreign-lambda`, but instead of generating code to call an external function, the body of the C procedure is directly given in `STRING ...`:

      (define my-strlen
        (foreign-lambda* int ((c-string str))
          "int n = 0;
           while(*(str++)) ++n;
           C_return(n);") )

      (my-strlen "one two three")             ==> 13

  For obscure technical reasons you should use the `C_return` macro instead of the normal `return` statement to return a result from the foreign lambda body as some cleanup code has to be run before execution commences in the calling code.

### foreign-safe-lambda

`(foreign-safe-lambda RETURNTYPE NAME ARGTYPE ...)`syntax

  This is similar to `foreign-lambda`, but also allows the called function to call Scheme functions. See Callbacks.

### foreign-safe-lambda*

`(foreign-safe-lambda* RETURNTYPE ((ARGTYPE VARIABLE)...) STRING ...)`syntax

  This is similar to `foreign-lambda*`, but also allows the called function to call Scheme functions and allocate Scheme data-objects. See Callbacks.

### foreign-primitive

`(foreign-primitive [RETURNTYPE] ((ARGTYPE VARIABLE) ...) STRING ...)`syntax

  This is also similar to `foreign-lambda*` but the code will be executed in a primitive CPS context, which means it will not actually return, but call its continuation on exit. This means that code inside this form may allocate Scheme data on the C stack (the nursery) with `C_alloc` (see below). You can return multiple values inside the body of the `foreign-primitive` form by using the following C code:

      C_word av[N + 2] = { C_SCHEME_UNDEFINED, C_k, X1, ... };
      C_values(N + 2, av);

  where `N` is the number of values to be returned, and `X1, ...` are the results, which should be Scheme data objects. When returning multiple values, the return-type should be omitted. Of course, if you have to dynamically compute the values, you do not have to use C's array initialization syntax, but you can just assign them one by one.

  Returning just a single value can still be done via the `C_return(...)` macro.

## Callbacks

To enable an external C function to call back to Scheme, the form `foreign-safe-lambda` (or `foreign-safe-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` form.

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 (defined by `define-external`) do not capture the lexical environment.

Non-local exits leaving the scope of the invocation of a callback from Scheme into C will not remove the C call-frame from the stack (and will result in a memory leak). Note: The same applies to SRFI-18 threading, which is implemented with `call/cc`; additionally, if you enter one callback, switch threads and then exit a different callback, your program is likely to crash.

### define-external

`(define-external [QUALIFIERS] (NAME (ARGUMENTTYPE1 VARIABLE1) ...) RETURNTYPE BODY ...)`syntax
`(define-external NAME TYPE [INIT])`syntax

  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))

  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 ()
        "C_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 a 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`).

  Results of type `scheme-object` returned by `define-external` are always allocated in the secondary heap, that is, not in the stack.

### C_callback

    [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.

### C_callback_adjust_stack

    [C function] void C_callback_adjust_stack (C_word *ptr, int size)

The runtime-system uses the stack as a special allocation area and internally holds pointers to estimated limits to distinguish between Scheme data objects inside the stack from objects outside of it. If you invoke callbacks at wildly differing stack-levels, these limits may shift from invocation to invocation. Callbacks defined with `define-external` will perform appropriate adjustments automatically, but if you invoke `C_callback` manually, you should perform a `C_callback_adjust_stack` to make sure the internal limits are set properly. `ptr` should point to some data object on the stack and `size` is the number of words contained in the data object (or some estimate). The call will make sure the limits are adjusted so that the value pointed to by `ptr` is located in the stack.

## Locations

It is also possible to define variables containing unboxed C data, so called locations. It should be noted that locations may only contain simple data, that is: everything that fits into a machine word, and double-precision floating point values.

### define-location

`(define-location NAME TYPE [INIT])`syntax

  Identical to `(define-external NAME TYPE [INIT])`, but the variable is not accessible from outside of the current compilation unit (it is declared `static`).

### let-location

`(let-location ((NAME TYPE [INIT]) ...) BODY ...)`syntax

  Defines a lexically bound location.

### location

`(location NAME)`syntax
`(location X)`syntax
`#$`read

  This form returns a pointer object that contains the address of the variable `NAME`. If the argument to `location` is not a location defined by `define-location`, `define-external` or `let-location`, then

      (location X)

  is essentially equivalent to

      (make-locative X)

  (See the manual section on locatives for more information about locatives)

  Note that `(location X)` may be abbreviated as `#$X`.

      (define-external foo int)
      ((foreign-lambda* void (((c-pointer int) ip)) "*ip = 123;")
        (location foo))
      foo                                                                    ==> 123

  This facility is especially useful in situations, where a C function returns more than one result value:

      #>
      #include <math.h>
      <#

      (define modf
        (foreign-lambda double "modf" double (c-pointer double)) )

      (let-location ([i double])
        (let ([f (modf 1.99 (location i))])
          (print "i=" i ", f=" f) ) )

  See location and c-string* for a tip on returning a `c-string*` type.

  `location` returns a value of type `c-pointer`, when given the name of a callback-procedure defined with `define-external`.

Previous: Module (chicken flonum)

Next: Module (chicken format)