## Foreign type specifiers

Here is a list of valid foreign type specifiers for use in accessing external objects.

### Void

`void` type

  Specifies an undefined return value. Not allowed as argument type.

### Boolean

`bool` type

  As argument: any value (`#f` is false (zero), anything else is true (non-zero).

  As result: anything different from 0 and the `NULL` pointer is `#t`.

  This type maps to `int` in both C and C++.

### Characters

`char` type
`unsigned-char` type

  A signed or unsigned character.

  As an argument, the input Scheme character is cast to C `char` or `unsigned char`, resulting in an 8-bit value. A Scheme character with an integer value outside 0-127 (signed) or 0-255 (unsigned) will be silently truncated to fit; in other words, don't feed it UTF-8 data.

  As a return type, accepts any valid Unicode code point; the return type is treated as a C int, and converted to a Scheme character.

### Integers

`byte` type
`unsigned-byte` type

  An 8-bit integer value in range -128 - 127 (byte) or 0 - 255 (unsigned byte). Values are cast to and from C `char` or `unsigned char` type, so values outside this 8-bit range will be unceremoniously truncated.

`short` type
`unsigned-short` type

  A short integer number in 16-bit range. Maps to C `short` or `unsigned short`.

`int` type
`unsigned-int` type
`int32` type
`unsigned-int32` type

  An integer number in fixnum range (-1073741824 to 1073741823, i.e. 31 bit signed). `unsigned-int` further restricts this range to 30 bit unsigned (0 to 1073741823). `int` maps to C type `int` and `int32` maps to `int32_t`.

  As an argument type, these expect a fixnum value, and as a return type they return a fixnum. Values outside the ranges prescribed above are silently truncated; you should use e.g. `integer` if you need the full 32-bit range. Note: `int32` is not recognized as an argument type prior to CHICKEN 4.7.2.

  Notes for 64-bit architectures:

  - C's `int` is 32 bits on most 64-bit systems (LP64), so `int` and `int32` are functionally (if not semantically) equivalent.
  - The fixnum type is larger than 32 bits and consequently the entire signed or unsigned 32-bit range is available for this type on 64-bit systems. However, for compatibility with 32-bit systems it is probably unwise to rely on this. If you need a 32-bit range, you should use (unsigned) `integer` or `integer32`.

`integer` type
`unsigned-integer` type
`integer32` type
`unsigned-integer32` type

  A fixnum or integral flonum, mapping to `int` or `int32_t` or their unsigned variants. When outside of fixnum range the value will overflow into a flonum.

  C's `int` is 32 bits on most 64-bit systems (LP64), so `integer` and `integer32` are functionally (if not semantically) equivalent.

`integer64` type
`unsigned-integer64` type

  A fixnum or integral flonum, mapping to `int64_t` or `uint64_t`. When outside of fixnum range the value will overflow into a flonum.

  On a 32-bit system, the effective precision of this type is 52 bits plus the sign bit, as it is stored in a `double` flonum. (In other words, numbers between 2^52 and 2^64-1 can be represented but there are gaps in the sequence; the same goes for their negative counterparts.) On a 64-bit system the range is 62 bits plus the sign bit, the maximum range of a fixnum. (Numbers between 2^62 and 2^64-1 have gaps.)

  `unsigned-integer64` is not valid as a return type until CHICKEN 4.6.4.

`long` type
`unsigned-long` type

  Either a fixnum or a flonum in the range of an (unsigned) machine long. Similar to `integer32` on 32-bit systems or `integer64` on 64-bit.

`size_t` type

  A direct mapping to C's `size_t`.

### Floating-point

`float` type
`double` type

  A floating-point number. If an exact integer is passed as an argument, then it is automatically converted to a float.

`number` type

  A floating-point number. Similar to `double`, but when used as a result type, then either an exact integer or a floating-point number is returned, depending on whether the result fits into an exact integer or not.

### Strings

`c-string` type
`nonnull-c-string` type

  A zero-terminated C string. The argument value `#f` is allowed and is passed as a `NULL` pointer; similarly, a NULL pointer is returned as `#f`. Note that the string contents are copied into (automatically managed) temporary storage with a zero byte appended when passed as an argument. Also, a return value of this type is copied into garbage collected memory using `strcpy(3)`.

  For the `nonnull-` variant, passing `#f` will raise an exception, and returning a NULL pointer will result in undefined behavior (e.g. a segfault).

`c-string*`type
`nonnull-c-string*`type

  Similar to `c-string` and `nonnull-c-string`, but if used as a result type, the pointer returned by the foreign code will be freed (using the C library's `free(3)`) after copying. This type specifier is not valid as a result type for callbacks defined with `define-external`.

`unsigned-c-string` type
`nonnull-unsigned-c-string` type
`unsigned-c-string*`type
`nonnull-unsigned-c-string*`type

  Same as `c-string`, `nonnull-c-string`, etc. but mapping to C's `unsigned char *` type.

`c-string-list` type
`c-string-list*`type

  Takes a pointer to an array of C strings terminated by a `NULL` pointer and returns a list of strings. The starred version `c-string-list*` also releases the storage of each string and the pointer array afterward using `free(1)`.

  Only valid as a result type, and can only be used with non-callback functions.

`symbol` type

  A symbol, which will be passed to foreign code as a zero-terminated string.

  When declared as the result of foreign code, the result should be a string and a symbol with the same name will be interned in the symbol table (and returned to the caller). Attempting to return a NULL string will raise an exception.

### Bytevectors

`blob` type
`nonnull-blob` type

  A blob object, passed as a pointer to its contents. Permitted only as argument type, not return type.

  Arguments of type `blob` may optionally be `#f`, which is passed as a NULL pointer. For the `nonnull-` variant, passing a `#f` value will raise an exception.

`u8vector` type
`u16vector` type
`u32vector` type
`u64vector` type
`s8vector` type
`s16vector` type
`s32vector` type
`s64vector` type
`f32vector` type
`f64vector` type
`nonnull-u8vector` type
`nonnull-u16vector` type
`nonnull-u32vector` type
`nonnull-u64vector` type
`nonnull-s8vector` type
`nonnull-s16vector` type
`nonnull-s32vector` type
`nonnull-s64vector` type
`nonnull-f32vector` type
`nonnull-f64vector` type

  A SRFI-4 number-vector object, passed as a pointer to its contents. These are allowed only as argument types, not as return types.

  The value `#f` is also allowed and is passed to C as a NULL pointer. For the `nonnull-` variants, passing `#f` will raise an exception.

### Pointers

`c-pointer` type
`(c-pointer TYPE)`type
`nonnull-c-pointer` type
`(nonnull-c-pointer TYPE)`type

  An operating-system pointer or a locative. `c-pointer` is untyped, whereas `(c-pointer TYPE)` points to an object of foreign type TYPE.

  The value `#f` is allowed and is passed to C as a `NULL` pointer; similarly, NULL is returned as `#f`. For the two `nonnull-` variants, passing `#f` will raise an exception, and returning NULL will result in a null `pointer` object.

  (Note: It is still possible to deliberately pass a null pointer through a `nonnull-c-pointer` by manually creating a null pointer object, e.g. via `(address->pointer 0)`.)

`pointer-vector` type
`nonnull-pointer-vector` type

  A vector of foreign pointer objects; see Pointer vectors. Permitted only as an argument type, not as return type. This type was introduced in CHICKEN 4.6.3.

  A pointer vector contains a C array of void pointers, and the argument is passed as a `void **` pointer to these contents. Just as for bytevector types, you must somehow communicate the length of this array to the callee; there is no sentinel node or NULL terminator.

  `#f` is allowed and passed as a `NULL` pointer. For the `nonnull-` variant, passing a `#f` value will raise an exception.

`(ref TYPE)`type

  A C++ reference type. Reference types are handled the same way as pointers inside Scheme code.

`(function RESULTTYPE (ARGUMENTTYPE1 ... [...]) [CALLCONV])`type

  A function pointer. `CALLCONV` specifies an optional calling convention and should be a string. The meaning of this string is entirely platform dependent. The value `#f` is also allowed and is passed as a `NULL` pointer.

### Scheme objects

`scheme-object` type

  An arbitrary, raw Scheme data object (immediate or non-immediate). A `scheme-object` is passed or returned as a `C_word`, the internal CHICKEN type for objects. Typically, this consists of an object header and tag bits. It is up to you to build or take apart such objects using the core library routines in `chicken.h` and `runtime.c`.

  More information on object structure can be found in Data representation.

`scheme-pointer` type
`(scheme-pointer TYPE)`type
`nonnull-scheme-pointer` type
`(nonnull-scheme-pointer TYPE)`type

  An untyped pointer to the contents of a non-immediate Scheme object; for example, the raw byte contents of a string. Only allowed as an argument type, not a return type.

  The optional element type `TYPE` may be used to specify what C type should be used in the generated code. This avoids the need to cast the argument.

  The value `#f` is also allowed and is passed as a `NULL` pointer. For the `nonnull-` variant, passing `#f` will raise an exception.

  Don't confuse this type with `(c-pointer ...)` which means something different (a machine-pointer object).

  `scheme-pointer` is typically used to get a pointer to the raw byte content of strings and blobs. But if you pass in a SRFI-4 vector, you will get a pointer to a blob object header (not the blob's contents), which is almost certainly wrong. Instead, convert to a blob beforehand, or use a SRFI-4 specific type.

### User-defined C types

`(struct NAME)`type

  A struct of the name `NAME`, which should be a string.

  Structs cannot be directly passed as arguments to foreign functions, nor can they be result values. However, pointers to structs are allowed.

`(union NAME)`type

  A union of the name `NAME`, which should be a string.

  Unions cannot be directly passed as arguments to foreign functions, nor can they be result values. However, pointers to unions are allowed.

`(enum NAME)`type

  An enumeration type. Handled internally as an `integer`.

### C++ types

`(instance CNAME SCHEMECLASS)`type

  A pointer to a C++ class instance wrapped into a Scheme object instance. `CNAME` should designate the name of the C++ class, and `SCHEMECLASS` should be the class that wraps the instance pointer.

  To use this, an extension will be required that provides an object-creation- and access-interface compatible to coops or tinyclos. Specifically, it should provide the following operations:

       (make SCHEMECLASS 'this POINTER)
       (slot-ref INSTANCE 'this)

`(instance-ref CNAME SCHEMECLASS)`type

  A reference to a C++ class instance.

`(template TYPE ARGTYPE ...)`type

  A C++ template type. For example `vector<int>` would be specified as `(template "vector" int)`.

  Template types cannot be directly passed as arguments or returned as results. However, pointers to template types are allowed.

### Type qualifiers

`(const TYPE)`type

  The foreign type `TYPE` with an additional `const` qualifier.

### Map of foreign types to C types

Foreign type | C type
--- | ---
`bool` | `int`
`[unsigned-]char` | `[unsigned] char`
`[unsigned-]byte` | `[unsigned] char`
`[unsigned-]short` | `[unsigned] short`
`[unsigned-]int` | `[unsigned] int`
`[unsigned-]int32` | `[unsigned] int32_t`
`[unsigned-]integer` | `[unsigned] int`
`[unsigned-]integer32` | `[unsigned] int32_t`
`[unsigned-]integer64` | `[unsigned] int64_t`
`[unsigned-]long` | `[unsigned] long`
`size_t` | `size_t`
`float` | `float`
`double` | `double`
`number` | `double`
`[nonnull-]c-pointer` | `void *`
`[nonnull-]pointer-vector` | `void **`
`[nonnull-]blob` | `unsigned char *`
`[nonnull-]u8vector` | `unsigned char *`
`[nonnull-]s8vector` | `char *`
`[nonnull-]u16vector` | `unsigned short *`
`[nonnull-]s16vector` | `short *`
`[nonnull-]u32vector` | `uint32_t *`
`[nonnull-]s32vector` | `int32_t *`
`[nonnull-]u64vector` | `uint64_t *`
`[nonnull-]s64vector` | `int64_t *`
`[nonnull-]f32vector` | `float *`
`[nonnull-]f64vector` | `double *`
`[nonnull-]c-string` | `char *`
`[nonnull-]unsigned-c-string` | `unsigned char *`
`c-string-list` | `char **`
`symbol` | `char *`
`void` | `void`
`([nonnull-]c-pointer TYPE)` | `TYPE *`
`([nonnull-]scheme-pointer TYPE)` | `TYPE *`
`(enum NAME)` | `enum NAME`
`(struct NAME)` | `struct NAME`
`(ref TYPE)` | `TYPE &`
`(template T1 T2 ...)` | `T1<T2, ...>`
`(union NAME)` | `union NAME`
`(function RTYPE (ATYPE ...) [CALLCONV])` | `[CALLCONV] RTYPE (*)(ATYPE, ...)`
`(instance CNAME SNAME)` | `CNAME *`
`(instance-ref CNAME SNAME)` | `CNAME &`

Previous: Accessing external objects

Next: Embedding