Specifying And Using Foreign Types in OpenMCL


Table of Contents

Overview
Syntax of foreign type specifiers
Functional reference
ccl:def-foreign-type [Macro]
ccl:make-record [Macro]
rlet [Macro]
ccl:rletz [Macro]
pref [Macro]

Overview

OpenMCL 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 OpenMCL via its interface database, though it's also possible to define foreign types interactively and/or programmatically.

OpenMCL'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; OpenMCL uses some escaping conventions to allow keywords to be used to denote these names.

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 (:SIGNED 8) under Darwin, or as (:UNSIGNED 8) under LinuxPPC.

  • 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 strucure 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 OpenMCL.

Functional reference

ccl:def-foreign-type [Macro]

Syntax

ccl:def-foreign-type name foreign-type-spec

Description

If name is non-NIL, defines name to be an alias for the foreign type specified by foreign-type-spec. If foreign-type-spec is a named structure or union type, additionally defines that structure or union type.

If name is NIL, foreign-type-spec must be a named foreign struct or union definition, in which case the foreign structure or union definition is put in effect.

[Note that there are separate namespaces for type names and for struct/union names.]

Arguments

 

name

NIL or a keyword; the keyword may contain escaping constructs.

foreign-type-spec

A foreign type specifier, whose syntax is (loosely) defined above.

ccl:make-record [Macro]

Syntax

ccl:make-record typespec &rest initforms

Description

typespec is interpreted as a foreign type specifier or, if a keyword and not a defined foreign type, as the name of a foreign record (struct or union) type. If an appropriate type or record type can't be found at macroexpand time, an error is signalled; otherwise, the type's size is determined and code is generated to heap-allocate and initialize an instance of that type. If typespec denotes a scalar type, initforms can contain a single value that can be coerced to that type; if typespec denotes a record type, initforms should be a list of 0 or more field names and initial values which can be coerced to the type of the specified field. (There isn't a good way to initialize individual fields of an array type, or to initialize record-typed fields of a record type.)

Record fields that aren't explicitly initialized are set to binary 0.

The value of the ccl:make-record form is a MACPTR which encapulates the address of the allocated memory block.

Arguments

 

typespec

A foreign type specifier or foreign record name.

initforms

As described above

rlet [Macro]

Syntax

rlet (var typespec &rest initforms)* &body body

Description

Executes body in an environment in which each var is bound to a MACPTR encapuslating the address of a stack-allocated foreign memory block, allocated and initialized from typespec and initforms as per ccl:make-record. Returns whatever value(s) body returns.

Record fields that aren't explicitly initialized have unspecified contents.

Arguments

 

var

A symbol (a lisp variable)

typespec

A foreign type specifier or foreign record name.

initforms

As described above, for ccl:make-record

ccl:rletz [Macro]

Syntax

rletz (var typespec &rest initforms)* &body body

Description

Executes body in an environment in which each var is bound to a MACPTR encapuslating the address of a stack-allocated foreign memory block, allocated and initialized from typespec and initforms as per ccl:make-record.

Returns whatever value(s) body returns.

Unlike rlet, record fields that aren't explicitly initialized are set to binary 0.

Arguments

 

var

A symbol (a lisp variable)

typespec

A foreign type specifier or foreign record name.

initforms

As described above, for ccl:make-record

pref [Macro]

Syntax

pref ptr accessor-form

Description

References an instance of a foreign type (or a component of a foreign type) accessible via ptr.

accessor-form can be a foreign type or record name, or a keyword symbol composed of a foreign type or record name followed by one or more record field names, separated by dots. Individual components of an accessor form may need to follow escaping conventions if the foreign type or field names contain upper-case characters.

Expands into code which references the indicated scalar type or component, or returns a pointer to a composite type.

PREF can be used with SETF.

RREF is a deprecated alternative to PREF. It accepts a :STORAGE keyword and rather loudly ignores it.

Arguments

 

ptr

a MACPTR.

accessor-form

See above.