Next Previous Up Top Contents Index

1.2 Overview

1.2.2 C functions in Dylan

When you use the interface definition language to describe a C function to the Dylan compiler, the compiler generates a new Dylan function. This wrapper function accepts Dylan arguments and returns Dylan results. It converts each of its arguments from a Dylan object to a corresponding C value before calling the C function it wraps. The C-FFI converts any results that the C function returns into Dylan objects before returning them to the caller.

In order for Dylan to be able to call into C correctly, C functions must be described to Dylan in the same detail a C header file would provide a calling C program. Specifically, for every function we must provide the C name and the type of its arguments and results. As with struct definitions, these types are indicated by naming the designator classes corresponding to the C types involved in the C-FFI description of the C function.

The following is an example of defining and using wrapper functions. Suppose we have the following extern C function declaration:

extern double cos (double angle);

We describe C functions to Dylan using the C-FFI macro define C-function:

define C-function C-cos
  parameter angle :: <C-double>;
  result    cos   :: <C-double>;
  c-name: "cos"
end C-function;

The name appearing immediately after the define C-function is the name we want to give to the Dylan variable to which our wrapper function will be bound. We call it C-cos. We also give the actual C name of the function we want to wrap as the value of the keyword c-name:.

Once we have compiled the definition -- and assuming the compiled version of the C library implementing cos has been linked in with the Dylan application -- we can call the wrapper function just like any other Dylan function:

? C-cos(0.0);
1.0

As we noted above, when values are passed back and forth between Dylan and C, the C-FFI performs automatic conversions. In this case, the type of the parameter and the result are both fundamental numeric types which means that the C-FFI will accept and return Dylan floats, converting to and from raw C floats as necessary.

As well as making C functions available to Dylan code, the C-FFI allows us to make Dylan functions available to call from C code. We do this by defining a C-callable wrapper function. A C-callable wrapper is a Dylan function that a C program can call. The C-callable wrapper has a C calling convention. When a C program calls a C-callable wrapper, the C-FFI performs the necessary data conversions and then invokes a Dylan function.

You can pass C-callable wrappers into C code for use as callbacks. You can also give them names visible in C, so that C clients of Dylan code can call into Dylan directly by invoking a named function.

The argument and result conversions performed by C-callable wrappers are just like those done within Dylan wrapper functions. The macro that defines C-callable wrappers is called define C-callable-wrapper and we describe it in detail later. For now, consider the following simple example. Suppose we have a C extern function declaration AddDouble:

extern double AddDouble (double x, double y);

This function is intended to return the sum of two double values. Instead of implementing the function in C, we can implement it in Dylan using Dylan's generic function +. All we need to do is define a C-callable wrapper for +, as follows:

define C-callable-wrapper AddDoubleObject of \+
  parameter x :: <C-double>;
  parameter y :: <C-double>;
  c-name: "AddDouble";
end C-callable-wrapper;

We can now call AddDouble in C. Our wrapper will be invoked, the C arguments will be converted and passed to Dylan's + generic function, and then the result of the computation will be converted and passed back to C:

{
  extern double AddDouble (double x, double y);
  double result;

  result = AddDouble(1.0, 2.0);
}

The C-FFI binds the Dylan variable AddDoubleObject to a Dylan object representing the function pointer of the C-callable wrapper. This reference allows the C-callable wrapper to be passed to a C function expecting a callback argument.


C FFI and Win 32 Reference - 31 MAR 2000

Next Previous Up Top Contents Index