You are looking at historical revision 17605 of this page. It may differ significantly from its current revision.

  1. C interface
    1. Temporary stack
      1. C_save
      2. C_restore
    2. Type/value predicates
      1. C predicates
        1. C_truep
        2. C_immediatep
        3. C_fitsinfixnump
        4. C_ufitsinfixnump
      2. Scheme predicates
        1. C_zero_length_p
      3. C_unboundvaluep
      4. C_boundp
      5. C_blockp
      6. C_immp
      7. C_forwardedp
      8. C_flonump
      9. C_stringp
      10. C_symbolp
      11. C_pairp
      12. C_closurep
      13. C_vectorp
      14. C_vectorp
      15. C_portp
      16. C_structurep
      17. C_locativep
      18. C_charp
      19. C_booleanp
      20. C_eofp
      21. C_undefinedp
      22. C_fixnump
      23. C_nfixnump
      24. C_pointerp
      25. C_taggedpointerp
      26. C_swigpointerp
      27. C_anypointerp
      28. C_lambdainfop
      29. C_byteblockp
      30. C_specialp
      31. C_nullp
      32. C_anyp
    3. Constructors for immediate Scheme objects
      1. C_fix
      2. C_make_character
      3. C_mk_bool
      4. C_mk_nbool
      5. C_SCHEME_END_OF_LIST
      6. C_word C_SCHEME_END_OF_FILE
      7. C_word C_SCHEME_FALSE
      8. C_word C_SCHEME_TRUE
    4. Constructors for non-immediate Scheme objects
      1. C_string
      2. C_string2
      3. C_intern2
      4. C_intern3
      5. C_pair
      6. C_flonum
      7. C_int_to_num
      8. C_mpointer
      9. C_vector
      10. C_list
      11. C_closure
    5. Memory allocation
      1. C_alloc
      2. C_SIZEOF_LIST
      3. C_SIZEOF_STRING
      4. C_SIZEOF_VECTOR
      5. C_SIZEOF_INTERNED_SYMBOL
      6. C_SIZEOF_PAIR
      7. C_SIZEOF_FLONUM
      8. C_SIZEOF_POINTER
      9. C_SIZEOF_LOCATIVE
      10. C_SIZEOF_TAGGED_POINTER
    6. Accessors
      1. C_character_code
      2. C_unfix
      3. C_flonum_magnitude
      4. C_c_string
      5. C_num_to_int
      6. C_pointer_address
      7. C_header_size
      8. C_header_bits
      9. C_block_item
      10. C_u_i_car
      11. C_u_i_cdr
      12. C_port_file
      13. C_data_pointer
    7. C_make_header
    8. C_mutate
    9. C_symbol_value
    10. GC interface
      1. C_gc_protect
      2. C_gc_unprotect
      3. C_pre_gc_hook
      4. C_post_gc_hook
    11. Type-specific predicates
      1. Vectors
        1. C_vemptyp
        2. C_notvemptyp
      2. Numbers
        1. C_u_i_exactp
        2. C_u_i_inexactp
      3. Pointers
        1. C_null_pointerp
      4. Ports
        1. C_tty_portp
      5. Fixnums
        1. C_i_fixnumevenp
        2. C_i_fixnumoddp
      6. Structures
        1. C_i_structurep
      7. Characters
        1. C_u_i_char_alphabeticp
        2. C_u_i_char_numericp
        3. C_u_i_char_whitespacep
        4. C_u_i_char_upper_casep
        5. C_u_i_char_lower_casep
    12. Other Scheme procedures from C
      1. C_eqp
      2. C_equalp
      3. C_i_pairp
      4. C_i_not_pair_p
    13. An example for simple calls to foreign code involving callbacks
    14. Notes:

C interface

The following functions and macros are available for C code that invokes Scheme or foreign procedures that are called by Scheme:

Temporary stack

C_save

[C macro] void C_save (C_word x) :

Saves the Scheme data object x on the temporary stack.

C_restore

[C macro] void C_restore

Pops and returns the topmost value from the temporary stack.

Type/value predicates

When writing C code that accepts Scheme objects you often need to do checking what type of object is passed. These can help you determine the type of an object.

C predicates

These return regular C integer values (ie, zero is false, nonzero true).

C_truep
[C macro] int C_truep(C_word x)

Is x a truthy value, i.e. anything except C_SCHEME_FALSE?

C_immediatep
[C macro] int C_immediatep(C_word x)

Is x an immediate object? (see below for a definition)

C_fitsinfixnump
[C macro] int C_fitsinfixnump(int number)

Will number fit in a fixnum? It will fit when there is room for one additional type bit to tag it as a fixnum (assuming one bit is already used for the sign). In practice this means that the number's top two bits must be identical.

C_ufitsinfixnump
[C macro] int C_ufitsinfixnump(unsigned int number)

Like C_fitsinfixnump but for unsigned integers. This checks the top two bits are zero, since fixnums always carry a sign.

Scheme predicates

These return Scheme booleans (ie, C_SCHEME_TRUE or C_SCHEME_FALSE). This means they can be used directly from Scheme using ##core#inline.

C_zero_length_p
[C macro] C_word C_zero_length_p(C_word x)

Is x a Scheme object of zero length? Only accepts non-immediate objects.

C_unboundvaluep

[C macro] C_word C_unboundvaluep(C_word x)

Is x the special unbound variable placeholder C_SCHEME_UNBOUND?

C_boundp

[C macro] C_word C_boundp(C_word x)

Is x a bound value? Only accepts non-immediate objects.

C_blockp

[C macro] C_word C_blockp(C_word x)

Is x a "block" value?

A "block" value is a value that contains a memory block, i.e. is not an immediate value.

C_immp

[C macro] C_word C_immp(C_word x)

Is x an immediate value?

C_forwardedp

[C macro] C_word C_forwardedp(C_word x)

Is x a GC-forwarded object?

C_flonump

[C macro] C_word C_flonump(C_word x)

Is x a Scheme flonum object? Accepts only non-immediate objects.

C_stringp

[C macro] C_word C_stringp(C_word x)

Is x a Scheme string object? Accepts only non-immediate objects.

C_symbolp

[C macro] C_word C_symbolp(C_word x)

Is x a symbol? Accepts only non-immediate objects.

C_pairp

[C macro] C_word C_pairp(C_word x)

Is x a pair? Accepts only non-immediate objects.

C_closurep

[C macro] C_word C_closurep(C_word x)

Is x a closure? Accepts only non-immediate objects.

C_vectorp

[C macro] C_word C_vectorp(C_word x)

Is x any kind of vector? Accepts only non-immediate objects.

This returns true for both regular heterogenous R5RS vectors and bytevectors ("blobs"). However, it does not return true for SRFI-4 vectors, as those are actually bytevectors wrapped in a structure with a type tag.

C_vectorp

[C macro] C_word C_bytevectorp(C_word x)

Is x a bytevector ("blob")? Accepts only non-immediate objects.

C_portp

[C macro] C_word C_portp(C_word x)

Is x a port object? Accepts only non-immediate objects.

C_structurep

[C macro] C_word C_structure(C_word x)

Is x a structure (record) object? Accepts only non-immediate objects.

C_locativep

[C macro] C_word C_locativep(C_word x)

Is x a locative object? Accepts only non-immediate objects.

C_charp

[C macro] C_word C_charp(C_word x)

Is x a character object?

C_booleanp

[C macro] C_word C_booleanp(C_word x)

Is x a boolean object?

C_eofp

[C macro] C_word C_eofp(C_word x)

Is x the #!eof object?

C_undefinedp

[C macro] C_word C_undefinedp(C_word x)

Is x the undefined value?

C_fixnump

[C macro] C_word C_fixnump(C_word x)

Is x a fixnum object?

C_nfixnump

[C macro] C_word C_nfixnump(C_word x)

Is x not a fixnum object?

C_pointerp

[C macro] C_word C_pointerp(C_word x)

Is x a C pointer object? Only accepts non-immediate objects.

C_taggedpointerp

[C macro] C_word C_taggedpointerp(C_word x)

Is x a tagged pointer object? Only accepts non-immediate objects.

C_swigpointerp

[C macro] C_word C_swigpointerp(C_word x)

Is x a SWIG pointer object? Only accepts non-immediate objects.

C_anypointerp

[C macro] C_word C_anypointerp(C_word x)

Is x any type of pointer object? Only accepts non-immediate objects.

C_lambdainfop

[C macro] C_word C_lambdainfop(C_word x)

Is x a lambda-info object? Only accepts non-immediate objects.

C_byteblockp

[C macro] C_word C_byteblockp(C_word x)

Is x a "byteblock" object? Only accepts non-immediate objects.

Strings, flonums, bytevectors and lambda-info objects are considered "byteblock" objects, as they are not containers for Scheme objects but simply point to contiguous memory ranges of bytes.

C_specialp

[C macro] C_word C_specialp(C_word x)

Is x a "special" object? Only accepts non-immediate objects.

Closures, ports, pointers and locatives are considered "special" objects, as they are not containers for Scheme objects (and they are not byte blocks either), so they have to be treated specially by the GC.

C_nullp

[C macro] C_word C_nullp(C_word x)

Is x the empty list, i.e. is it C_SCHEME_END_OF_LIST?

C_anyp

[C macro] C_word C_anyp(C_word x)

Always returns C_SCHEME_TRUE.

Constructors for immediate Scheme objects

"immediate" Scheme objects are objects that are represented directly by a C_word. There's no additional memory used by them.

C_fix

[C macro] C_word C_fix (int integer)

C_make_character

[C macro] C_word C_make_character (int char_code)

C_mk_bool

[C macro] C_word C_mk_bool(int truth_value)

C_mk_nbool

[C macro] C_word C_mk_nbool(int truth_value_to_negate)

C_SCHEME_END_OF_LIST

[C macro] C_SCHEME_END_OF_LIST

C_word C_SCHEME_END_OF_FILE

[C macro] C_SCHEME_END_OF_FILE

C_word C_SCHEME_FALSE

[C macro] C_SCHEME_FALSE

C_word C_SCHEME_TRUE

[C macro] C_SCHEME_TRUE

Constructors for non-immediate Scheme objects

Non-immediate Scheme objects are still represented and passed around by a single C_word, but this is basically just a pointer to the start of the object (which should never be treated as such, use the accessor macros instead).

C_string

[C function] C_word C_string (C_word **ptr, int length, char *string)

C_string2

[C function] C_word C_string2 (C_word **ptr, char *zero_terminated_string)

C_intern2

[C function] C_word C_intern2 (C_word **ptr, char *zero_terminated_string)

C_intern3

[C function] C_word C_intern3 (C_word **ptr, char *zero_terminated_string, C_word initial_value)

C_pair

[C function] C_word C_pair (C_word **ptr, C_word car, C_word cdr)

C_flonum

[C function] C_word C_flonum (C_word **ptr, double number)

C_int_to_num

[C function] C_word C_int_to_num (C_word **ptr, int integer)

C_mpointer

[C function] C_word C_mpointer (C_word **ptr, void *pointer)

C_vector

[C function] C_word C_vector (C_word **ptr, int length, ...)

C_list

[C function] C_word C_list (C_word **ptr, int length, ...)

C_closure

[C function] C_word C_closure (C_word **ptr, int length, C_word procedure, ...)

These functions allocate memory from ptr and initialize a fresh data object. The new data object is returned. ptr should be the address of an allocation pointer created with C_alloc.

To find out how big the memory block should be, use the C_SIZEOF_* macros described below.

Here's an example how to create a closure that accepts a vector, stores the Scheme numbers 1, 2 and 3 and a given string in it and returns that vector to its continuation:

#>

#include <assert.h>

void fill_vector(C_word c, C_word closure, C_word vec)
{
  C_word kontinuation = C_block_item(closure, 1);

  C_block_item(vec, 0) = C_fix(1);
  C_block_item(vec, 1) = C_fix(2);
  C_block_item(vec, 2) = C_fix(3);
  C_block_item(vec, 3) = C_block_item(closure, 2);

  C_kontinue(kontinuation, vec);
}

void one_two_three(C_word c, C_word self, C_word k, C_word str)
{
  /*
   * Allocate room on the stack to hold the closure:  1 word for
   * the type tag, 1 word for the procedure and 2 words for the
   * values "closed over"; this procedure's continuation "k" and
   * the argument "str".  We could also use C_alloc(4).
   */
  C_word closure[4], *cp = closure;

  /* Create the closure.  It holds 3 values, not counting the tag */
  C_word closure_object = C_closure(&cp, 3, (C_word)fill_vector, k, str);

  /*
   * After this, cp points just beyond the last word of the allocated
   * data and closure_object is an opaque representation of the newly
   * created closure as a whole, i.e. the following relations hold:
   */
  assert(  (closure + 4) == cp  );
  assert(  C_block_header(closure_object) == (*closure)  );
  assert(  C_data_pointer(closure_object) == (closure + 1)  );
  assert(  C_block_item(closure_object, 0) == (*(closure + 1))  );

  /* Make a vector of 4 objects and use closure_object as continuation */
  C_allocate_vector(6, (C_word)NULL, closure_object, C_fix(4),
                    C_SCHEME_FALSE,  /* not a byte vector */
                    C_SCHEME_FALSE,  /* initialization value. Don't care */
                    C_SCHEME_FALSE); /* don't align at 8 bytes */
  /* .. C_allocate_vector does not return ... */
}
<#


(define one-two-three (foreign-primitive ((scheme-object str)) "one_two_three(C_c, C_self, C_k, str);"))
;; Or, more direct/lowlevel:
;; (define one-two-three (##core#primitive "one_two_three"))

(print (one-two-three "hi"))

This is equivalent to the following in Scheme:

(define (one-two-three str)
  (let ((fill-vector (lambda (vec)
                       (vector-set! vec 0 1)
                       (vector-set! vec 1 2)
                       (vector-set! vec 2 3)
                       (vector-set! vec 3 str)
                       vec)))
    (fill-vector (make-vector 4 #f))))

(print (one-two-three "hi"))

Memory allocation

These can be used to allocate memory for non-immediate objects.

C_alloc

[C macro] C_word* C_alloc (int words)

Allocates memory from the C stack (C_alloc) and returns a pointer to it. words should be the number of words needed for all data objects that are to be created in this function. Note that stack-allocated data objects have to be passed to Scheme callback functions, or they will not be seen by the garbage collector. This is really only usable for callback procedure invocations, make sure not to use it in normal code, because the allocated memory will be re-used after the foreign procedure returns. When invoking Scheme callback procedures a minor garbage collection is performed, so data allocated with C_alloc will already have moved to a safe place.

Note that C_alloc is really just a wrapper around alloca, and can also be simulated by declaring a stack-allocated array of C_words:

C_SIZEOF_LIST

[C macro] int C_SIZEOF_LIST (int length)

C_SIZEOF_STRING

[C macro] int C_SIZEOF_STRING (int length)

C_SIZEOF_VECTOR

[C macro] int C_SIZEOF_VECTOR (int length)

C_SIZEOF_INTERNED_SYMBOL

[C macro] int C_SIZEOF_INTERNED_SYMBOL (int length)

C_SIZEOF_PAIR

[C macro] int C_SIZEOF_PAIR

C_SIZEOF_FLONUM

[C macro] int C_SIZEOF_FLONUM

C_SIZEOF_POINTER

[C macro] int C_SIZEOF_POINTER

C_SIZEOF_LOCATIVE

[C macro] int C_SIZEOF_LOCATIVE

C_SIZEOF_TAGGED_POINTER

[C macro] int C_SIZEOF_TAGGED_POINTER

These are macros that return the size in words needed for a data object of a given type.

Accessors

C_character_code

[C macro] int C_character_code (C_word character)

C_unfix

[C macro] int C_unfix (C_word fixnum)

C_flonum_magnitude

[C macro] double C_flonum_magnitude (C_word flonum)

C_c_string

[C function] char* C_c_string (C_word string)

C_num_to_int

[C function] int C_num_to_int (C_word fixnum_or_flonum)

C_pointer_address

[C function] void* C_pointer_address (C_word pointer)

These macros and functions can be used to convert Scheme data objects back to C data. Note that C_c_string() returns a pointer to the character buffer of the actual Scheme object and is not zero-terminated.

C_header_size

[C macro] int C_header_size (C_word x)

C_header_bits

[C macro] int C_header_bits (C_word x)

Return the number of elements and the type-bits of the non-immediate Scheme data object x.

C_block_item

[C macro] C_word C_block_item (C_word x, int index)

This macro can be used to access slots of the non-immediate Scheme data object x. index specifies the index of the slot to be fetched, starting at 0. Pairs have 2 slots, one for the car and one for the cdr. Vectors have one slot for each element.

C_u_i_car

[C macro] C_word C_u_i_car (C_word x)

C_u_i_cdr

[C macro] C_word C_u_i_cdr (C_word x)

Aliases for C_block_item(x, 0) and C_block_item(x, 1), respectively.

C_port_file

[C macro] C_word C_port_file (C_word x)

Alias for (FILE *)C_block_item(x, 0). To be used with port objects representing files (but will not work on sockets, for example).

C_data_pointer

[C macro] void* C_data_pointer (C_word x)

Returns a pointer to the data-section of a non-immediate Scheme object.

C_make_header

[C macro] C_word C_make_header (C_word bits, C_word size)

A macro to build a Scheme object header from its bits and size parts.

C_mutate

[C function] C_word C_mutate (C_word *slot, C_word val)

Assign the Scheme value val to the location specified by slot. If the value points to data inside the nursery (the first heap-generation), then the garbage collector will remember to handle the data appropriately. Assigning nursery-pointers directly will otherwise result in lost data. Note that no copying takes place at the moment when C_mutate is called, but later - at the next (minor) garbage collection.

C_symbol_value

[C macro] C_word C_symbol_value (C_word symbol)

Returns the global value of the variable with the name symbol. If the variable is unbound C_SCHEME_UNBOUND is returned. You can set a variable's value with C_mutate(&C_symbol_value(SYMBOL), VALUE).

GC interface

C_gc_protect

[C function] void C_gc_protect (C_word *ptrs[], int n)

Registers n variables at address ptrs to be garbage collection roots. The locations should not contain pointers to data allocated in the nursery, only immediate values or pointers to heap-data are valid. Any assignment of potential nursery data into a root-array should be done via C_mutate(). The variables have to be initialized to sensible values before the next garbage collection starts (when in doubt, set all locations in ptrs to C_SCHEME_UNDEFINED) C_gc_protect may not called before the runtime system has been initialized (either by CHICKEN_initialize, CHICKEN_run or CHICKEN_invoke.

For a slightly simpler interface to creating and using GC roots see CHICKEN_new_gc_root.

C_gc_unprotect

[C function] void C_gc_unprotect (int n)

Removes the last n registered variables from the set of root variables.

C_pre_gc_hook

[C Variable] void (*C_pre_gc_hook)(int mode)

If not NULL, the function pointed to by this variable will be called before each garbage collection with a flag indicating what kind of collection was performed (either 0 for a minor collection or 2 for a resizing collection). A "resizing" collection means a secondary collection that moves all live data into a enlarged (or shrinked) heap-space. Minor collections happen very frequently, so the hook function should not consume too much time. The hook function may not invoke Scheme callbacks.

Note that resizing collections may be nested in normal major collections.

C_post_gc_hook

[C Variable] void (*C_post_gc_hook)(int mode, long ms)

If not NULL, the function pointed to by this variable will be called after each garbage collection with a flag indicating what kind of collection was performed (either 0 for a minor collection, 1 for a major collection or 2 for a resizing collection). Minor collections happen very frequently, so the hook function should not consume too much time. The hook function may not invoke Scheme callbacks. The ms argument records the number of milliseconds required for the garbage collection, if the collection was a major one. For minor collections the value of the ms argument is undefined.

Type-specific predicates

The following are predicates to ask information about an object once its type is already known. If you call it on any object of another type, it is not defined what will happen and likely your program will crash.

Vectors

C_vemptyp
[C macro] C_word C_vemptyp(C_word v)

Is the (byte- or heterogenous) vector v empty? Only accepts non-immediate values.

C_notvemptyp
[C macro] C_word C_notvemptyp(C_word v)

Is the (byte- or heterogenous) vector v nonempty? Only accepts non-immediate values.

Numbers

C_u_i_exactp
[C macro] C_word C_u_i_exactp(C_word x)

Is x an exact number (i.e., a fixnum)? Assumes that x is already known to be a number.

C_u_i_inexactp
[C macro] C_word C_u_i_inexactp(C_word x)

Is x an inexact number (i.e., not a fixnum)? Assumes that x is already known to be a number.

Pointers

C_null_pointerp
[C macro] C_word C_null_pointerp(C_word x)

Is x a NULL pointer? Assumes that x is already known to be of a pointer type.

Ports

C_tty_portp
[C macro] C_word C_tty_portp(C_word x)

Is x a TTY port object? Assumes that x is already known to be of a port type.

Fixnums

C_i_fixnumevenp
[C macro] C_word C_i_fixnumevenp(C_word x)

Is x an even fixnum? Assumes that x is already known to be of a fixnum type.

C_i_fixnumoddp
[C macro] C_word C_i_fixnumoddp(C_word x)

Is x an odd fixnum? Assumes that x is already known to be of a fixnum type.

Structures

C_i_structurep
[C macro] C_word C_i_structurep(C_word x, C_word s)

Is x a structure (record) object with type tag s? Is completely safe to use, because it checks whether x is an immediate or not.

Characters

C_u_i_char_alphabeticp
[C macro] C_word C_u_i_char_alphabeticp(C_word c)

Is c an alphabetic character? Assumes that c is already known to be a character. This uses the ASCII character set.

C_u_i_char_numericp
[C macro] C_word C_u_i_char_numericp(C_word c)

Is c a numeric character? Assumes that c is already known to be a character. This uses the ASCII character set.

C_u_i_char_whitespacep
[C macro] C_word C_u_i_char_whitespacep(C_word c)

Is c a whitespace character? Assumes that c is already known to be a character. This uses the ASCII character set.

C_u_i_char_upper_casep
[C macro] C_word C_u_i_char_upper_casep(C_word c)

Is c an uppercase character? Assumes that c is already known to be a character. This uses the ASCII character set.

C_u_i_char_lower_casep
[C macro] C_word C_u_i_char_lower_casep(C_word c)

Is c a lowercase character? Assumes that c is already known to be a character. This uses the ASCII character set.

Other Scheme procedures from C

There are a number of Scheme procedures that have a direct C implementation, so you can call them from C too.

C_eqp

[C macro] C_word C_eqp(C_word a, C_word b)

The C version of (eq? a b).

C_equalp

[C macro] C_word C_equalp(C_word a, C_word b)

The C version of (equal? a b).

C_i_pairp

[C function] C_i_pair_p(C_word x)

The C version of (pair? x).

C_i_not_pair_p

[C macro] C_i_not_pair_p(C_word x)

The C version of (not (pair? x)).

An example for simple calls to foreign code involving callbacks

% cat foo.scm
#>
extern int callout(int, int, int);
<#

(define callout (foreign-safe-lambda int "callout" int int int))

(define-external (callin (scheme-object xyz)) int
  (print "This is 'callin': " xyz)
  123)

(print (callout 1 2 3))
% cat bar.c
#include <stdio.h>
#include "chicken.h"

extern int callout(int, int, int);
extern int callin(C_word x);

int callout(int x, int y, int z)
{
  C_word *ptr = C_alloc(C_SIZEOF_LIST(3));
  C_word lst;

  printf("This is 'callout': %d, %d, %d\n", x, y, z);
  lst = C_list(&ptr, 3, C_fix(x), C_fix(y), C_fix(z));
  return callin(lst);  /* Note: `callin' will have GC'd the data in `ptr' */
}
% csc foo.scm bar.c -o foo
% foo
This is 'callout': 1, 2, 3
This is 'callin': (1 2 3)
123

Notes:


Previous: Other support procedures

Next: Extensions