Next Previous Up Top Contents Index

1.2 Overview

1.2.1 C types in Dylan

When you use the interface definition language to describe a C type to the Dylan compiler, the compiler generates a new Dylan class. This class is said to designate the C type, which means that it carries with it the essential properties of the C type such as its size and alignment.

You can use this designator class in subsequent interface definition forms to specify which elements involve the designated C type. A designator class also carries with it the information on how to interpret the untyped C data as a tagged Dylan object.

The C-FFI library contains predefined designator classes for C's fundamental types like int and double. The names of these predefined Dylan classes are formed from the C name of the fundamental type being designated. The designator class name for a particular C type formed using Dylan's standard class-naming convention; it is prefixed with "C-", hyphenated if it contains more than one word, and enclosed in angle brackets. For example, the C-FFI library provides the class <C-int> to designate the C type int; it designates double by the class <C-double>, and unsigned long by the class <C-unsigned-long>.

Note: Since Dylan variable names are compared without sensitivity to case, the capitalization of the "C" in the names above, and in other Dylan names appearing in this document, is not binding and can safely be ignored.

The C-FFI library also provides predefined classes designating pointers to C's fundamental numeric types. To do so, it adds a * to the fundamental C type designator. For example <C-double*> designates the C type double *.

The following is an example of defining and using designator classes. Suppose we have the following C struct:

typedef struct {
  unsigned short x_coord; 
  unsigned short y_coord; 
} Point;

We describe C structs to Dylan using the macro define C-struct:

define C-struct <Point>
  slot x-coord :: <C-unsigned-short>;
  slot y-coord :: <C-unsigned-short>;
end C-struct;

This form defines a new designator class <Point> for a structure type corresponding to the C type Point. We designate the types of the slots of <Point> using the Dylan classes designating the C types used in the definition of Point. In this case, both slots are of the C type unsigned short which is designated by the predefined class <C-unsigned-short>. The information about the C type unsigned short carried by this designator class allows the compiler to compute the size, alignment, and layout of the struct. The compiler records the struct's size and alignment and associates them with <Point>. The designator class <Point> can then be used in the definition of other types, functions, and variables. For example, we could describe

typedef struct {
  Point start;
  Point end;
} LineSegment;

like this:

define C-struct <LineSegment>
  slot start :: <Point>;
  slot end   :: <Point>;
end C-struct;

As well as acting as a static information carrier for use in other FFI definitions, a designator class can also be instantiable, in which case Dylan uses an instance of the designator class to represent an object of the C type it designates when that object is passed from the "C world" to the "Dylan world".

Note: Only classes that designate C pointer types can be instantiated in this way. Instances of C's fundamental numeric value types like int, char, and double are just converted to an equivalent Dylan object with the same value. The <Point> class is not an instantiable class in Dylan because there is nothing in Dylan that corresponds to a C struct. However, the C-FFI does provide a Dylan representation of a pointer to a C struct.

To illustrate, here is an example interaction involving a C struct containing some pointer-typed slots and some slots whose types are fundamental numeric types:

define C-struct <Example>
  slot count        :: <C-int>;
  slot statistic    :: <C-double>;
  slot data         :: <C-char*>;
  slot next         :: <Example*>;
  pointer-type-name :: <Example*>;
end C-struct;

This example defines the two designator types <Example> and <Example*>; the slots count and statistic have fundamental numeric types while data and next have pointer types. The getter and setter methods for the slots are defined for instances of <Example*>.

Suppose there is a function current-example that returns an initialized <Example*> struct. The following transactions illustrate what you get when you read the slots of the structure it returns:

? define variable example = current-example();
// Defined example 

? example.count; 4

? instance?(example.count, <integer>); #t

? example.statistic; 10.5

? instance?(example.statistic, <float>); #t

The interactions above show that if we access structure slots that were defined as being of one of C's fundamental numeric types, we get a Dylan number of the equivalent value. The same thing happens if an imported C function returns a fundamental numeric type: a Dylan number with the same value appears in Dylan. Similarly, when setting slots in structs expecting numbers or passing objects out to C functions expecting numeric arguments, you should provide a Dylan number, and the C-FFI will convert it automatically to its C equivalent.

? example.data;
{<C-char> pointer #xff5e00}

? instance?(example.data, <C-char*>); #t

? example.next; {<Example> pointer #xff5f00}

? instance?(example.next, <Example*>); #t

The interactions above show that accessing structure slots with a pointer type results in an instance of the Dylan class that designates that type. Again, the same thing happens if an imported C function returns a pointer type: an instance of the corresponding designator class is created. Similarly, when setting slots in structs expecting pointers or passing objects out to C functions expecting pointer arguments, you should provide an instance of the Dylan designator class for that pointer type, and the C-FFI will convert it automatically to the raw C pointer value.

Later sections describe all the macros available for defining C types and the functions available for manipulating them.


C FFI and Win 32 Reference - 31 MAR 2000

Next Previous Up Top Contents Index