Previous Chapter | Next Section | Table of Contents | Glossary | Index |
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.
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, MACPTR
s—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
.
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
(SETF (NS:NS-SIZE-WIDTH s) w (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
(LET ((P (MAKE-GCABLE-RECORD :NS-POINT))) (NS:INIT-NS-POINT P X Y) p)
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)))
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 |