5.4. C Calling conventions

ECL is implemented using either a C or a C++ compiler. This is not a limiting factor, but imposes some constraints on how these languages are used to implement functions, multiple values, closures, etc. In particular, while C functions can be called with a variable number of arguments, there is no facility to check how many values were actually passed. This forces us to have two types of functions in ECL

The previous conventions set some burden on the C programmer that calls ECL, for she must know the type of function that is being called and supply the right number of arguments. This burden disappears for Common Lisp programmers, though.

As an example let us assume that the user wants to invoke two functions which are part of the ANSI standard and thus are exported with a C name. The first example is cl_cos, which takes just one argument and has a signature cl_object cl_cos(cl_object).

#include <math.h>
cl_object angle = ecl_make_double_float(M_PI);
cl_object c = cl_cos(angle);
printf("\nThe cosine of PI is %g\n", ecl_double_float(c));

The second example also involves some Mathematics, but now we are going to use the C function corresponding to +. As described in the C dictionary, the C name for the plus operator is cl_P and has a signature cl_object cl_P(cl_narg narg,...). Our example now reads as follows

cl_object one = ecl_make_fixnum(1);
cl_object two = cl_P(2, one, one);
cl_object three = cl_P(3, one, one, one);
printf("\n1 + 1 is %d\n", ecl_fixnum(two));
printf("\n1 + 1 + 1 is %d\n", ecl_fixnum(three));

Note that most Common Lisp functions will not have a C name. In this case one must use the symbol that names them to actually call the functions, using cl_funcall or cl_apply. The previous examples may thus be rewritten as follows

/* Symbol + in package CL */
cl_object plus = ecl_make_symbol("+","CL");
cl_object one = ecl_make_fixnum(1);
cl_object two = cl_funcall(3, plus, one, one);
cl_object three = cl_funcall(4, plus, one, one, one);
printf("\n1 + 1 is %d\n", ecl_fixnum(two));
printf("\n1 + 1 + 1 is %d\n", ecl_fixnum(three));

Another restriction of C and C++ is that functions can only take a limited number of arguments. In order to cope with this problem, ECL uses an internal stack to pass any argument above a hardcoded limit, ECL_C_CALL_ARGUMENTS_LIMIT, which is as of this writing 63. The use of this stack is transparently handled by the Common Lisp functions, such as apply, funcall and their C equivalents, and also by a set of macros, cl_va_arg, which can be used for coding functions that take an arbitrary name of arguments.