Chicken » Accessing external objects

## 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 calling this C function:

      C_values(N + 2, C_SCHEME_UNDEFINED, C_k, X1, ...)

  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.

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

## Returning large objects or chunks of memory to Scheme

When you call a C function which needs to return quantities of data, several issues arise:

- the size of the nursery is limited, so C_alloc can cause stack overflow
- if you malloc in C, and intend to leave it there, and directly access parts of that data from Scheme, you will need C accessor functions to pinpoint the parts you need and return them as Scheme objects; you will also need a finalizer if you intend for this data to be garbage-collected
- building up lists or other complex Scheme structures from individual pairs, or putting non-immediate objects into vectors, is cumbersome in C

So some would advise you to just return a pointer to Scheme, use memcpy or any other function(s) which you need to get the data into CHICKEN-managed memory and into the desired kind of data structure, then free the C data. For this example, we are trying to return an array of doubles into an f64vector; we can accomplish that by adding a specialized copy function to the C library being integrated:

    void CopyResults(double* vector) {
        memcpy(vector, bezierBuffer, totalOutputPoints * sizeof(double));
    }

    // The original C function which takes an array of doubles,
    // does some sort of transmogrification,
    // retains a new malloc'd array of the results
    // and returns the count
    int GenerateResults(double* vector, int count) {
        ...
    }

and the "egg" which calls the C functions can be implemented like this:

    (module memcpy-demo (input->output)
        (import chicken scheme foreign)
        (use srfi-4)

        (define CopyResults (foreign-lambda void "CopyResults" f64vector))

        (define GenerateResults (foreign-lambda integer "GenerateResults" f64vector integer))

        (define (input->output input)
            (let* ([size (GenerateResults input (f64vector-length input))]
                   [vect (make-f64vector size)])
                (printf "returned size ~a~%" size)
                (CopyResults vect)
                vect)))

The foreign-lambda takes care of the details in this case so that an f64vector allocated in the nursery can be treated as a plain old array of doubles in C (assuming your C compiler uses 64-bit values for double).

Various eggs provide other examples, and some of them do it more efficiently too, but this method is relatively clean and compact.

Previous: Interface to external functions and variables

Next: Foreign type specifiers