MacroPackage: ffToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version


Arguments: name &rest slots

This macro is obsolete and kept for backward compatibility only. Please use def-foreign-type.

This macro returns name if name is a symbol or (car name) if name is a list but it is used for its side effects. The side effects are (1) defining a C type which can be created by Lisp; and (2) defining constructor and accessor functions which can be used, respectively, to create instances of the C type and access the values of the C type. You can specify that instances be located in Lisp space (the default in most cases), which means the instance may be moved by the garbage collector, or in foreign (also called C or malloc) space. Objects in C space are never moved. We will return to the difference between Lisp and foreign space below.

You can also control whether accessor functions and/or constructor functions are created. Note that if you want to define a type whose only use is as a part of another type, you should call def-c-typedef instead of def-c-type.

The argument name must be a symbol or a list whose first element is a symbol. The symbol becomes a name for the C data type. If the value of name is a list, the elements after the symbol (the first element) must be the keywords :in-foreign-space, :no-defuns, or :no-constructor. Any one or two or all three may be included in the list.

If you specify :in-foreign-space in the list, any instance of the type created with either the constructor function (described below) or make-cstruct will be located in foreign space and never moved by the garbage collector. Such objects can be repeatedly accessed by either C or Lisp since the addresses known to C will never become invalid. These types can be used as a communication channel between C and Lisp. If that keyword is not used, instances will be created in Lisp space. If an object is stored in Lisp space, great care must be used when accessing it from C since whenever Lisp code is run, the object may be moved. Typically, such items are only accessed by C once and are thereafter used only by Lisp or are disposed of.

If you specify :no-defuns in the list, no accessor functions will be defined. You typically do this when your code is well debugged and such functions are not necessary to run your application, thus saving space. If you do not specify :no-defuns, accessor functions will be defined. The accessor functions are named by appending -[slot-name] to the symbol. If there are no slots (see below), the symbol itself denotes the accessor function. Accessor functions always take either the object or its address as an argument and may take further arguments if more are necessary.

If you specify :no-constructor, no constructor function will be created. Then, you will only be able to create new objects of the type with make-cstruct taking the (quoted) symbol as an argument. Note that an object of a type defined with def-c-typedef cannot be created even with make-cstruct. Calling the constructor function (if one is created, it will be named make- followed by the symbol) or make-cstruct will cause the new object itself to be returned if the object is in Lisp space and the address of the new object (suitable to be passed to C) if the object is in foreign space.

You must also specify one or more data-types. More than one are allowed for backwards compatibility with defcstruct. We recommend using one data-type only and will not discuss using more than one. The data-type may be one of the following (in general, datatypes are C datatypes prefixed with a ':` to make them keywords):

:char | :signed-char | :byte
:unsigned-char | :unsigned-byte
:int | :long | :signed | :signed-int | :signed-long
:unsigned-int | :unsigned-long | :unsigned
:short | :signed-short
:float | :single-float | :short-float
:double | :double-float | :long-float

:bit integer
integer data-type
:union (slot-name data-type)+
:struct (slot-name data-type)+

You specify exactly the keyword named in the first eight cases. The types specified on a single line (and separated by vertical bars) are equivalent types: thus you achieve the same thing by specifying :char or :byte, both are equivalent. If you specify :bit (for a bit array), you follow it with an integer which indicates the number of elements in the array. You may specify a * followed by a data-type (that is anything in the list) to get a pointer to that object. You may specify an integer followed by a data-type to get an array of objects of that type. Note that * and integer are recursively defined so as many *`s and integer`s as you want may be used.

You may specify a structure or a union with :struct or :union, followed by lists (as many as you wish) of the form

(slot-name data-type)

Here slot-name is a symbol and data-type is a data-type defined above.

Finally, the value of data-type may be any symbol specifying a data-type already defined with def-c-type or def-c-typedef.

As we said above, objects of this type are created with constructor functions or with make-cstruct. In either case, the value returned is either the object itself (for objects in Lisp space) or the address of the object (for objects in foreign space). Note that the address will be understood by the accessor functions and can be passed to C, etc., but is just an integer as far as most Lisp functions are concerned.

Values stored in the various slots can be set with setf and the accessor function. Lisp values are converted to the appropriate C value when they are stored in most cases (or an error is signaled if that is not possible). When accessed, the C values are converted to the appropriate Lisp value, again in most cases and when possible. Note that there are special accessors when you use already defined structures to build new structures in foreign space.

See ftype.htm for information on foreign types in Allegro CL and foreign-functions.htm for general information on foreign functions in Allegro CL.

Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version