Next Previous Up Top Contents Index

1.7 Functions

define C-callable-wrapper

Definition macro

Summary

Makes a Dylan function callable from C by describing a C contract for the function.

Signature

define C-callable-wrapper [dylan-rep-name] 
of dylan-function [parameter-spec; ...] [;] [result-spec] [;] [function-options][;] end [C-callable-wrapper]

Arguments

dylan-rep-name
A Dylan variable name.

dylan-function
An instance of <function>.

parameter-spec

result-spec

function-options
A property list.

Library

c-ffi

Module

c-ffi

Description

Makes a Dylan function callable from C by describing a C contract for the function. In order to generate a correct C-callable function wrapper, the same information about the function must be given as would be needed by C callers, typically provided by extern declarations for the function in a C header file: the types of its parameters and results.

The result of processing a define C-callable-wrapper definition is a function with a C entry point with the contract described. This function takes C values as arguments, converting them to Dylan representations according to the types declared for the parameters of the C function before calling the Dylan function with them. If the C function was described as returning results, the results of the call to the Dylan function are converted to C representations according to the declared types of those results before being returned to the C caller of the function.

The dylan-function is a Dylan function that accepts the correct number of parameters, and is called by the C callable wrapper.

The function-options are a property list. This list may contain a string value for the c-name keyword. If a c-name is specified, that name is made visible to C as the name of the generated C-callable wrapper function. Given a compatible extern declaration, this allows C code to call Dylan code simply by invoking a named function. The export: option takes the values #t or #f and indicates whether the c-name for the generated C-callable-wrapper function is to be exported from the library's .dll. #t means it is exported, #f means it is not. The default is #f. The c-modifiers: option is the same as in the c-function macro, except that the modifiers apply to the C function wrapper which is generated. See define C-function, page 48.

If dylan-rep-name is specified, it is bound to an instance of a function-pointer designator class identifying the generated C-callable wrapper function. You can pass this pointer to C code for use as, for example, a callback.

A parameter-spec has the following syntax:

[adjectives] parameter name :: c-type #key c-name 

If no parameters are specified, the C function is taken to have no arguments.

An adjective can be input, output, or both. The calling discipline is specified by the input and output adjectives.

If a parameter is output, the corresponding parameter is not passed to the Dylan function, but the Dylan function is expected to return an extra value that is placed in the location pointed to by the parameter. When the pointer is NULL, the extra value from the Dylan function is ignored. The type designated for the parameter must be a pointer type.

If a parameter is both input and output, the parameter must be a pointer type, and the value accepted by the Dylan function is the result. The functions pointer-value and pointer-value-setter perform the primitive Dylan-to-C and C-to-Dylan conversions as documented with the designator class of the pointer's contents type (see Table 1.1). The C-FFI signals an error if it cannot convert the object you attempt to store in the pointer to a compatible type. on that pointer. The Dylan function is expected to return an extra value which is placed into the location specified by the pointer passed to the C function. If the pointer passed to the C function is NULL, then the value passed to the Dylan function will be #f, and the extra value returned will be ignored.

There is currently no way to define a C-callable function that accepts a variable number of arguments.

A result-spec has the following syntax:

result name :: c-type 

If no result is specified, the C function defined does not return a value. It is defined as what in C terminology is known as a void function.

Example C declarations:

/* Compute the length of a string */
int strlen(char *string);

/* Set the given locations to values, returning an error code */

int fill_locations(int *loc1, int* loc2);

/* Read at most as far as indicated in max_then_read, updating it to contain how much was actually read */

void read_stuff(int *max_then_read);

Example FFI definitions:

define method dylan-strlen (string) => (length) ... end;

define C-callable-wrapper of dylan-strlen parameter string :: <C-char*>; result value :: <C-int>; c-name: "strlen"; end C-function;

define method dylan-fill-locations () => (return-code :: <integer>, val1 :: <integer>, val2 :: <integer>) ... end;

define C-callable-wrapper of dylan-fill-locations output parameter loc1 :: <C-int*>; output parameter loc2 :: <C-int*>; result return-code :: <C-int>; c-name: "fill_locations"; end C-function;

define method dylan-read-stuff (max :: <integer>) => (read :: <integer) ... end;

define C-callable-wrapper of dylan-read-stuff input output parameter max-then-read :: <C-int*>; c-name: "read_stuff"; end C-function;

Example C calls:

{
  int length, *loc1, *loc2, max_then_read;

length = strlen("ABC");

fill_locations(loc1, loc2);

max_then_read = 100 read_stuff(&max_then_read); }

In effect, a define C-callable-wrapper such as:

define C-callable-wrapper of foo
  parameter string :: <C-char*>;
  parameter count  :: <C-int>;
  result    value  :: <C-int>;
  c-name: "foo";
end C-function;

expands into something like:

%c-callable-function "foo" (c-string, c-count)
    let dylan-string 
      = %as-dylan-representation(<C-char*>, c-string);
    let dylan-count
      = %as-dylan-representation(<C-int>, c-count);
    let dylan-result 
      = foo(dylan-string, dylan-count);
    %as-c-representation(<C-int>, dylan-result);
  end;

where the % functions perform the primitive conversions between Dylan and C representations, checking that their arguments are compatible with the declared type.
Callback example:
? define C-function c-sort
    parameter strings     :: <C-string*>;
    parameter compare     :: <C-function-pointer>;
    result sorted-strings :: <C-string*>;
    c-name: "sort";
  end C-function;

// Defined c-sort.

? define C-callable-wrapper callback-for-< of \< parameter string1 :: <C-string>; parameter string2 :: <C-string>; result int :: <C-int>; end C-callable-wrapper;

// Defined callback-for-<

? callback-for-< {function pointer #xff6e00} ? c-sort(some-c-strings, callback-for-<); {<C-string> array}


C FFI and Win 32 Reference - 31 MAR 2000

Next Previous Up Top Contents Index