Embeddable Common Lisp supports all Common-Lisp data types exactly as defined in the [see ANSI]. All functions and macros are expected to behave as described in that document and in the HyperSpec [see HyperSpec] which is the online version of [see ANSI]. In other words, the Standard is the basic reference for Common Lisp and also for Embeddable Common Lisp, and this part of the manual just complements it, describing implementation-specific features such as:
In order to aid in locating these differences, this first part of the manual copies the structure of the ANSI Common-Lisp standard, having the same number of chapters, each one with a set of sections documenting the implementation-specific details.
The second goal of this document is to provide a reference for C programmers that want to create, manipulate and operate with Common Lisp programs at a lower level, or simply embedding Embeddable Common Lisp as a library.
The C/C++ reference evolves in parallel with the Common Lisp one, in the form of one section with the name "C Reference" for each chapter of the ANSI Common-Lisp standard. Much of what is presented in those sections is redundant with the Common Lisp specification. In particular, there is a one-to-one mapping between types and functions which should be obvious given the rules explained in the next section C Reference.
We must remark that the reference in this part of the manual is not enough to know how to embed Embeddable Common Lisp in a program. In practice the user or developer will also have to learn how to build programs (System building), interface with foreign libraries (Foreign Function Interface), manage memory (Memory Management), etc. These concepts are explained in a different (Embedding ECL) part of the book.
cl_object
ECL is designed around the basic principle that Common Lisp already provides everything that a programmer could need, orienting itself around the creation and manipulation of Common Lisp objects: conses, arrays, strings, characters, ... When embedding ECL there should be no need to use other C/C++ types, except when interfacing data to and from those other languages.
All Common Lisp objects are represented internally through the same C
type, cl_object
, which is either a pointer to a union type or an
integer, depending on the situation. While the inner guts of this type
are exposed through various headers, the user should never rely on these
details but rather use the macros and functions that are listed in this
manual.
There are two types of Common Lisp objects: immediate and memory
allocated ones. Immediate types fit in the bits of the cl_object
word, and do not require the garbage collector to be created. The list
of such types may depend on the platform, but it includes at least the
fixnum
and character
types.
Memory allocated types on the other hand require the use of the garbage
collector to be created. ECL abstracts this from the user providing
enough constructors, either in the form of Common Lisp functions
(cl_make_array
, cl_complex
,...), or in the form of
C/C++ constructors (ecl_make_symbol
, etc).
Memory allocated types must always be kept alive so that the garbage collector does not reclaim them. This involves referencing the object from one of the places that the collector scans:
For memory allocation details See Memory Management. For object implementation details See Manipulating Lisp objects.
As explained in the introduction, each of the chapters in the Common Lisp standard can also be implemented using C functions and types. The mapping between both languages is done using a small set of rules described below.
cl
) package are prefixed with the
characters cl_
, functions in the System (si
) and
Extensions (ext
) package are prefix with si_
, etc, etc.
cos
maps to cl_object cl_cos(cl_object)
, which takes a
single Lisp object and returns a Lisp object of type float
.
cl_object cl_list(cl_narg narg, ...)
, which can be invoked
without arguments, as in cl_list(0)
, with one, cl_list(1,
a)
, etc.
nil
. The extra values may be retrieved
immediately after the function call using the function
ecl_nth_value
.
In addition to the Common Lisp core functions (cl_*
), there exist
functions which are devoted only to C/C++ programming, with tasks such
as coercion of objects to and from C types, optimized functions, inlined
macroexpansions, etc. These functions and macros typically carry the
prefix ecl_
or ECL_
and only return one value, if any.
Most (if not all) Common Lisp functions and constructs available from C/C++ are available in “ANSI Dictionary” sections which are part of the [Standards] entries.
Some parts of the language are not available as C functions, even though they can be used in Common Lisp programs. These parts are either marked in the “ANSI Dictionary” sections using the tag Only in Common Lisp, or they are simply not mentioned (macros and special constructs). This typically happens with non-translatable constructs such as
with-open-files
cond
In most of those cases there exist straightforward alternatives using
the constructs and functions in ECL. For example, unwind-protect
can be implemented using a C macro which is provided by ECL
cl_env_ptr env = ecl_process_env(); ECL_UNWIND_PROTECT_BEGIN(env) { /* protected code goes here */ } ECL_UNWIND_PROTECT_EXIT { /* exit code goes here */ } ECL_UNWIND_PROTECT_END;
Common Lisp generic functions can be directly accessed using
funcall
or apply
and the function name, as shown in the
code below
cl_object name = ecl_make_symbol("MY-GENERIC-FUNCTION","CL-USER"); cl_object output = cl_funcall(2, name, argument);
Identifying these alternatives requires some knowledge of Common Lisp, which is why it is recommended to approach the embeddable components in ECL only when there is some familiarity with the language.