7.  Notes for Writing C/C++ Code Using Elk  

      This chapter describes general conventions and usage notes for Elk-based C/C++ code and introduces a few useful facilities that are not directly related to Scheme.

7.1.  Elk Include Files  

      Every C or C++ file using functions, macros, or variables defined by Elk must include the file scheme.h:

#include <scheme.h>      or:      #include "scheme.h"

      This include file resides in a subdirectory include of the directory where Elk has been installed on your system. You must insert a suitable -I option into your Makefiles to add this directory to the C compiler's search path. ``scheme.h'' includes several other Elk-specific include files from the same directory and, in addition, the standard C include files <stdio.h> and <signal.h>.

7.2.  Standard C and Function Prototypes  

      All the examples shown in this manual are written in ANSI/ISO C. This assumes that the Elk include files have been installed with function prototypes enabled. Whether or not function prototypes are enabled is controlled by a definition in the platform- and compiler-specific ``config/system'' file that has been selected for configuring Elk. However, if the include files have function prototypes disabled, prototypes are enable automatically if you are compiling your code with a C compiler that defines the symbol ``__STDC__'' as non-zero, or with a C++ compiler that defines ``__cplusplus''[note 1] .

      Elk include files that have been installed with function prototypes disabled can also be ``upgraded'' by defining the symbol ``WANT_PROTOTYPES'' before including ``scheme.h''. Similarly, include files installed without function prototypes can be used with a non-ANSI C compiler by defining the symbol ``NO_PROTOTYPES'' before including ``scheme.h''.

7.3.  External Symbols Defined by Elk  

      As extensions or applications are linked with Elk (regarless of whether dynamic loading or static linking is used), they can in general reference all external symbols exported by Elk. Of these, only the symbols described in this manual may be used safely. Use of other (private) symbols results in non-portable code, as the symbols may change their meaning or may even be removed from future releases of Elk. The same restriction applies to the macros and types defined by the include files of Elk.

      In addition to the symbols defined by the Scheme interpreter kernel, those exported by other Scheme extensions that are present in the same executable (or have been loaded earlier) can be referenced from within C/C++ code. These extensions are not subject of this manual; you should refer to the relevant documentation and the public include files that are part of the extensions.

      If Elk is linked with an application that has its own main() function, none of the functions exported by Elk must be used before the initial call to Elk_Init() (except Set_App_Name()).

7.4.  Calling Scheme Primitives  

      A large subset of the symbols exported by the Scheme interpreter is the set of functions implementing the Scheme primitives. These may be used safely by extensions and applications. There exists one C function for each Scheme primitive. Its name is that of the corresponding primitive with the following conversions applied:

The names of a few functions are derived differently as shown by this table:

+------------------------------------------+
|Scheme Primitive         C Function       |
+------------------------------------------+
|       <           P_Generic_Less()       |
|       >           P_Generic_Greater()    |
|       =           P_Generic_Equal()      |
|       <=          P_Generic_Eq_Less()    |
|       >=          P_Generic_Eq_Greater() |
|       1+          P_Inc()                |
|   1- and -1+      P_Dec()                |
|       +           P_Generic_Plus()       |
|       -           P_Generic_Minus()      |
|       *           P_Generic_Multiply()   |
|       /           P_Generic_Divide()     |
|      let*         P_Letseq()             |
+------------------------------------------+

      According to these rules, the primitive exact->inexact can be used from within C as P_Exact_To_Inexact(), the predicate integer? is available as P_Integerp(), etc. Authors of reusable Scheme extensions are encouraged to follow these (or similar) naming conventions in their code.

      All the functions implementing Scheme primitives (as well as special forms, which are treated as primitives in Elk) receive Scheme objects or arrays thereof as their arguments and return Scheme objects as their values. The underlying C type will be described in the next chapter. For the semantics of the non-standard Scheme primitives defined by Elk refer to the Reference Manual for the interpreter.

7.5.  Portable alloca()  

      Elk provides a portable variant of alloca() as a set of macros that can be used by extensions and applications. alloca(), which is supported by most modern UNIX systems and C compilers, allocates memory in the caller's stack frame; the memory is automatically released when the function returns. Elk simulates this functionality on the (rare) platforms where alloca() is not available.

      To allocate memory, the macro Alloca() is called with a variable to which the newly allocated memory is assigned, the type of that variable, and the number of bytes that are requested. The macro Alloca_End must be called (without an argument list) before returning from a function or block that uses Alloca(); this macro is empty on those platforms that support the ordinary alloca(). Finally, a call to the macro Alloca_Begin must be placed in the function's declarations. Alloca() usually is more efficient than malloc() and free(), and the memory need not be freed when the function is left prematurely because of an interrupt or by calling a continuation.

As an example, here is the skeleton of a function that is called with a filename prefix and a suffix, concatenates them (separated by a period), and opens the resulting file:

int some_function(char *prefix, char *suffix) {
    char *name;
    int len, fd;
    Alloca_Begin;

    len = strlen(prefix) + 1 + strlen(suffix) + 1;
    Alloca(name, char*, len);
    sprintf(name, "%s.%s", prefix, suffix);
    fd = open(name, ...);
    ...
    Alloca_End;
}

7.6.  Other Useful Macros and Functions  

      The preprocessor symbols ELK_MAJOR and ELK_MINOR expand to the major and minor version number of the current release of Elk. They did not exist in versions older than Elk 3.0.

      index(), bcopy(), bcmp(), and bzero() are defined as suitable macros on systems that do not have them in their C library; they may be used by source files that include ``scheme.h'', regardless of the actual platform.

Code linked with Elk may use the two functions

char *Safe_Malloc(unsigned size);
char *Safe_Realloc(char *old_pointer, unsigned size);
as alternatives to malloc() and realloc(). If the request for memory cannot be satisfied, the standard Elk error handler is called with a suitable error message.


Markup created by unroff 1.0,    September 24, 1996,    net@informatik.uni-bremen.de