# Embedding

Compiled Scheme files can be linked with C code, provided the Scheme code was compiled in embedded mode by passing `-DC_EMBEDDED` to the C compiler (this will disable generation of a `main()` function). `csc` will do this, when given the `-embedded` option. Alternatively pass `-embedded` to `csc`.
The following C API is available:

## CHICKEN_parse_command_line

     [C function] void CHICKEN_parse_command_line (int argc, char *argv[], int *heap, int *stack int *symbols)

Parse the programs command-line contained in `argc` and `argv` and return the heap-, stack- and symbol table limits given by runtime options of the form `-:...`, or choose default limits. The library procedure `argv` can access the command-line only if this function has been called by the containing application.

## CHICKEN_initialize

     [C function] int CHICKEN_initialize (int heap, int stack, int symbols, void *toplevel)

Initializes the Scheme execution context and memory. `heap` holds the number of bytes that are to be allocated for the secondary heap. `stack` holds the number of bytes for the primary heap. `symbols` contains the size of the symbol table. Passing `0` to one or more of these parameters will select a default size. `toplevel` should be a pointer to the toplevel entry point procedure. You should pass `C_toplevel` here. In any subsequent call to `CHICKEN_run` you can simply pass `NULL`. Calling this function more than once has no effect. If enough memory is available and initialization was successful, then `1` is returned, otherwise this function returns `0`.

## CHICKEN_run

     [C function] C_word CHICKEN_run (void *toplevel)

Starts the Scheme program. Call this function once to execute all toplevel expressions in your compiled Scheme program. If the runtime system was not initialized before, then `CHICKEN_initialize` is called with default sizes. `toplevel` is the toplevel entry-point procedure, you usually pass `C_toplevel` here. The result value is the continuation that can be used to re-invoke the Scheme code from the point after it called `return-to-host` (see below).
If you just need a Scheme interpreter, you can also pass `CHICKEN_default_toplevel` as the toplevel procedure, which just uses the default library units.
Once `CHICKEN_run` has been called, Scheme code is executing until all toplevel expressions have been evaluated or until `return-to-host` is called inside the Scheme program.

## return-to-host

     [procedure] (return-to-host)

Exits the Scheme code and returns to the invoking context that called `CHICKEN_run` or `CHICKEN_continue`.
After `return-to-host` has been executed and once `CHICKEN_run` returns, you can invoke callbacks which have been defined with `define-external`. The `eval` library unit also provides boilerplate callbacks, that simplify invoking Scheme code embedded in a C or C++ application a lot.

## CHICKEN_eval

     [C macro] int CHICKEN_eval (C_word exp, C_word *result)

Evaluates the Scheme object passed in `exp`, writing the result value to `result`. The return value is 1 if the operation succeeded, or 0 if an error occurred. Call `CHICKEN_get_error_message` to obtain a description of the error.

## CHICKEN_eval_string

     [C macro] int CHICKEN_eval_string (char *str, C_word *result)

Evaluates the Scheme expression passed in the string `str`, writing the result value to `result`.

## CHICKEN_eval_to_string

     [C macro] int CHICKEN_eval_to_string (C_word exp, char *result, int size)

Evaluates the Scheme expression passed in `exp`, writing a textual representation of the result into `result`. `size` should specify the maximal size of the result string.

## CHICKEN_eval_string_to_string

     [C macro] int CHICKEN_eval_string_to_string (char *str, char *result, int size)

Evaluates the Scheme expression passed in the string `str`, writing a textual representation of the result into `result`. `size` should specify the maximal size of the result string.

## CHICKEN_apply

     [C macro] int CHICKEN_apply (C_word func, C_word args, C_word *result)

Applies the procedure passed in `func` to the list of arguments `args`, writing the result value to `result`.

## CHICKEN_apply_to_string

     [C macro] int CHICKEN_apply_to_string (C_word func, C_word args, char *result, int size)

Applies the procedure passed in `func` to the list of arguments `args`, writing a textual representation of the result into `result`.

## CHICKEN_read

     [C macro] int CHICKEN_read (char *str, C_word *result)

Reads a Scheme object from the string `str`, writing the result value to `result`.

## CHICKEN_load

     [C macro] int CHICKEN_load (char *filename)

Loads the Scheme file `filename` (either in source form or compiled).

## CHICKEN_get_error_message

     [C macro] void CHICKEN_get_error_message (char *result, int size)

Returns a textual description of the most recent error that occurred in executing embedded Scheme code.

## CHICKEN_yield

     [C macro] int CHICKEN_yield (int *status)

If threads have been spawned during earlier invocations of embedded Scheme code, then this function will run the next scheduled thread for one complete time-slice. This is useful, for example, inside an idle handler in a GUI application with background Scheme threads. Note that the `srfi-18` library unit has to be linked in for this.
An example:

     % cat x.scm
     ;;; x.scm

     (define (bar x) (gc) (* x x))

     (define-external (baz (int i)) double
       (sqrt i))
     (return-to-host)

     % cat y.c
     /* y.c */

     #include <chicken.h>
     #include <assert.h>

     extern double baz(int);

     int main() {
       char buffer[ 256 ];
       int status;
       C_word val = C_SCHEME_UNDEFINED;
       C_word *data[ 1 ];

       data[ 0 ] = &val;

       CHICKEN_run(C_toplevel);

       status = CHICKEN_read("(bar 99)", &val);
       assert(status);

       C_gc_protect(data, 1);

       printf("data: %08x\n", val);

       status = CHICKEN_eval_string_to_string("(bar)", buffer, 255);
       assert(!status);

       CHICKEN_get_error_message(buffer, 255);
       printf("ouch: %s\n", buffer);

       status = CHICKEN_eval_string_to_string("(bar 23)", buffer, 255);
       assert(status);

       printf("-> %s\n", buffer);
       printf("data: %08x\n", val);

       status = CHICKEN_eval_to_string(val, buffer, 255);
       assert(status);
       printf("-> %s\n", buffer);

       printf("->` %g\n", baz(22));

       return 0;
     }

     % csc x.scm y.c -embedded

It is also possible to re-enter the computation following the call to `return-to-host` by calling `CHICKEN_continue`:

## CHICKEN_continue

     [C function] C_word CHICKEN_continue (C_word k)

Re-enters Scheme execution. `k` is the continuation received from the previous invocation of `CHICKEN_run` or `CHICKEN_continue`. When `return-to-host` is called again, this function returns another continuation that can be used to restart again.
If you invoke callbacks prior to calling `CHICKEN_continue`, make sure that the continuation is not reclaimed by garbage collection. This can be avoided by using `C_gc_protect` or gc-roots.
Another example:

     % cat x.scm
     (require-extension srfi-18)

     (define m (make-mutex))

     (define (t)
       (mutex-lock! m)
       (thread-sleep! 1)
       (print (thread-name (current-thread)))
       (mutex-unlock! m)
       (t) )

     (thread-start! (make-thread t 'PING!))
     (thread-start! (make-thread t 'PONG!))

     (let loop ()
       (return-to-host)
       (thread-yield!)
       (loop) )

     % cat y.c
     #include <chicken.h>

     int main()
     {
       C_word k = CHICKEN_run(C_toplevel);

       for(;;)
         k = CHICKEN_continue(k);

       return 0;
     }

     % csc x.scm y.c -embedded

It is advisable not to mix repeated uses of `CHICKEN_continue`/`return-to-host` (as in the example above) with callbacks. Once `return-to-host` is invoked, the runtime system and any Scheme code executed prior to the invocation is initialized and can be conveniently used via callbacks.
A simpler interface For handling GC-safe references to Scheme data are the so called gc-roots:

## CHICKEN_new_gc_root

     [C function] void* CHICKEN_new_gc_root ()

Returns a pointer to a GC root, which is an object that holds a reference to a Scheme value that will always be valid, even after a garbage collection. The content of the gc root is initialized to an unspecified value.

## CHICKEN_new_finalizable_gc_root

     [C function] void* CHICKEN_new_finalizable_gc_root ()

Similar to `CHICKEN_new_gc_root`, but allows the stored value to be finalized: if this gc root holds reference to an otherwise unreferenced data object that has a finalizer, the finalizer is still invoked.

## CHICKEN_delete_gc_root

     [C function] void CHICKEN_delete_gc_root (void *root)

Deletes the gc root.

## CHICKEN_gc_root_ref

     [C macro] C_word CHICKEN_gc_root_ref (void *root)

Returns the value stored in the gc root.

## CHICKEN_gc_root_set

     [C macro] void CHICKEN_gc_root_set (void *root, C_word value)

Sets the content of the GC root to a new value.
Sometimes it is handy to access global variables from C code:

## CHICKEN_global_lookup

     [C function] void* CHICKEN_global_lookup (char *name)

Returns a GC root that holds the global variable with the name `name`. If no such variable exists, `NULL` is returned.

## CHICKEN_global_ref

     [C function] C_word CHICKEN_global_ref (void *global)

Returns the value of the global variable referenced by the GC root `global`.

## CHICKEN_global_set

     [C function] void CHICKEN_global_set (void *global, C_word value)

Sets the value of the global variable referenced by the GC root `global` to `value`.

Previous: Foreign type specifiers
Next: Callbacks