Previous Chapter Next Section Table of Contents Glossary Index

Chapter 13. The Foreign-Function Interface

13.1. Specifying And Using Foreign Types

13.1.1. Overview

CCL provides a fairly rich language for defining and specifying foreign data types (this language is derived from CMUCL's "alien type" system.)

In practice, most foreign type definitions are introduced into CCL via its interface database (see ), though it's also possible to define foreign types interactively and/or programmatically.

CCL's foreign type system is "evolving" (a polite word for not-quite-complete): there are some inconsistencies involving package usage, for instance. Symbols used in foreign type specifiers should be keywords, but this convention isn't always enforced.

Foreign type, record, and field names are case-sensitive; CCL uses some escaping conventions (see ) to allow keywords to be used to denote these names. Type Annotations

As of version 1.2, CCL supports annotating the types of foreign pointers on Mac OS X. Forms that create pointers to foreign memory—that is, MACPTRs—store with the MACPTR object a type annotation that identifies the foreign type of the object pointed to. Calling PRINT-OBJECT on a MACPTR attempts to print information about the identified foreign type, including whether it was allocated on the heap or the stack, and whether it's scheduled for automatic reclamation by the garbage collector.

Support for type annotation is not yet complete. In particular, some uses of PREF and SLOT-VALUE do ot yet take type annotations into account, and neither do DESCRIBE and INSPECT. Foreign Types as Classes

Some types of foreign pointers take advantage of the support for type annotations, and pointers of these types can be treated as instances of known classes. Specifically, a pointer to an :<NSR>ect is recognized as an instance of the built-in class NS:NS-RECT, a pointer to an <NSS>ize is treated as an instance of NS:NS-SIZE, a pointer to an <NSP>oint is recognized as an instance of NS:NS-POINT, and a pointer to an <NSR>ange is recognized as an instance of NS:NS-RANGE.

A few more obscure structure types also support this mechanism, and it's possible that a future version will support user definition of similar type mappings.

This support for foreign types as classes provides the following conveniences for each supported type:

  • a PRINT-OBJECT method is defined

  • a foreign type name is created and treated as an alias for the corresponding type. As an example, the name :NS-RECT is a name for the type that corresponds to NS:NS-RECT, and you can use :NS-RECT as a type designator in RLET forms to specify a structure of type NS-RECT.

  • the class is integrated into the type system so that (TYPEP R 'NS:NS-RECT) is implemented with fair efficiency.

  • inlined accessor and SETF inverses are defined for the structure type's fields. In the case of an <NSR*gt;ect, for example, the fields in question are the fields of the embedded point and size, so that NS:NS-RECT-X, NS:NS-RECT-Y, NS:NS-RECT-WIDTH, NS-RECT-HEIGHT and SETF inverses are defined. The accessors and setter functions typecheck their arguments and the setters handle coercion to the appropriate type of CGFLOAT where applicable.

  • an initialization function is defined; for example,

    (NS:INIT-NS-SIZE s w h)

    is roughly equivalent to

          (NS:NS-SIZE-HEIGHT s) h)

    but might be a little more efficient.

  • a creation function is defined; for example

    (NS:NS-MAKE-POINT x y)

    is functionally equivalent to

  • a macro is defined which, like RLET, stack-allocates an instance of the foreign record type, optionally initializes that instance, and executes a body of code with a variable bound to that instance.

    For example,

    (ns:with-ns-range (r loc len)
      (format t "~& range has location ~s, length ~s" 
         (ns:ns-range-location r) (ns:ns-range-length r)))

13.1.2. Syntax of Foreign Type Specifiers

  • Some foreign types are builtin: keywords denote primitive,builtin types such as the IEEE-double-float type (denoted:DOUBLE-FLOAT), in much the same way as certain symbols(CONS, FIXNUM,etc.) define primitive CL types.

  • Constructors such as :SIGNED and :UNSIGNED can be used to denote signed and unsigned integer subtypes (analogous to the CL type specifiers SIGNED-BYTE and UNSIGNED-BYTE.) :SIGNED is shorthand for(:SIGNED 32) and :UNSIGNED is shorthand for (:UNSIGNED 32).

  • Aliases for other (perhaps more complicated) types can be defined via CCL:DEF-FOREIGN-TYPE (sort of like CL:DEFTYPE or the C typedef facility). The type :CHAR is defined as an alias for (:SIGNED8) on some platforms, as (:UNSIGNED 8) on others.

  • The construct (:STRUCT name) can be used to refer to a named structure type; (:UNION name)can be used to refer to a named union type. It isn't necessary to enumerate a structure or union type's fields in order to refer to the type.

  • If X is a valid foreign type reference,then (:* X) denotes the foreign type "pointer to X". By convention, (:* T) denotes an anonymous pointer type, vaguely equivalent to "void*" in C.

  • If a fieldlist is a list of lists, each of whose CAR is a foreign field name (keyword) and whose CADR is a foreign type specifier, then (:STRUCT name ,@fieldlist) is a definition of the structure type name, and (:UNION name ,@fieldlist) is a definition of the union type name. Note that it's necessary to define a structure or union type in order to include that type in a structure, union, or array, but only necessary to "refer to" a structure or union type in order to define a type alias or a pointer type.

  • If X is a defined foreign type , then (:array X &rest dims) denotes the foreign type "array of X". Although multiple array dimensions are allowed by the :array constructor, only single-dimensioned arrays are (at all) well-supported in CCL.

Previous Chapter Next Section Table of Contents Glossary Index