Structural Informatics Group (SIG) logo
Home | Projects | Demos | Downloads | Publications | Local Info | About Us | New site
Go to the first, previous, next, last section, table of contents.

Embedding Slisp in C

The files /include/seval.h and /c/seval.c allow slisp to be included as part of other C programs, so that it can be controlled in a different manner than the read-eval-print cycle that is used in xmain, the main program in xlisp. The primary motivation for this is to allow slisp to be controlled from a graphical user interface. For example, an slisp application could become a module within AVS, (Advanced Visualization System), or an object within a NeXTStep application.

The main routines are sl_Init, to initialize slisp, and sl_Eval_Str, which accepts a string describing an s-expression, calls slisp to evaluate it, and writes the results to an output string pointer (memory for the output string is allocated by seval.c). Slisp errors are written to the output string. There are also routines to get the C integer, float or string value of the current LISP expression. Since all of Slisp is supported, all primitive functions are available, as are any LISP functions via the LOAD lisp command.

Note that seval.c always disables debugging and tracing even if the lisp programmer sets *BREAKENABLE* or *TRACENABLE* to T. This is because the debug loop in xlisp requires more input, which is incompatible with the notion of sending all input in a string, and then receiving all output in another string.

The externally callable functions are defined in seval.h, which should be included in the external program, along with a compiler directive -I$(SLISPROOT)/include to find the include file, where SLISPROOT is the location of the top level slisp directory. The main program should be linked with up to four libraries: LOCALLIBES XCORELIBES XLISPLIBES NETLIBES OTHERLIBES, in that order. All the libraries are automatically created in the LIBPATH directory, which is specified in the appropriate slisp/systems file.

LOCALLIBES is libseval.a, and is the library for the routines in seval.c.

XCORELIBES are the routines from xcore that implement the basic xlisp functions designed by Dave Betz. This library is different for each application. For sl the library is called libsl.a.

XLISPLIBES is the common library containing all new c-coded primitive functions added to slisp by any compiled application. This file is called libslisp.a.

NETLIBES contains analogous routines to seval.c, defined in c/netseval.c, that allow an slisp application to act as a network client for another slisp server (see the section on client-server operations). This library is only required if the application being embedded has been compiled with the xnet module.

OTHERLIBES are any other libraries potentially needed by an application on a given machine, as defined in the appropriate slisp/systems file.

slisp/c contains the source code for seval.c, as well as an example embedded application. The Makefile for each application has a target called "local_client". When this target is made the c/Makefile is used to compile an example local client whose name is appc, where app is the name of the executable shell for the application. For example, for sl the local client is slc.

For the local client c/Makefile defines LOCAL_CLIENT, and compiles c/sl_client.c. This program can be used as a template for including the seval.c functions.

In addition when "make check" is run for an application, the c/Makefile "check" target is run, which creates an executable "local_check" from client_check.c. client_check.c provides examples for using the routines in seval.c.

A somewhat simpler example is shown below, which is essentially the same as sl_client.c, but without all the makefile flags.

# Example Makefile that searches libraries in HOME/lib
# which is where the slisp libraries are created by default.
# Search application library sl before slisp 
LIBS= -L$HOME/lib -lseval -lsl -lslisp  -lnetseval 
CFLAGS= -I$HOME/src/slisp/include #location of seval.h

slc:slc.o
	cc slc.o $(LIBS) -o slc

/******************************************************************/
/* slc.c */

#include "seval.h"
#include <stdio.h>

#define BUF_SIZ 4000

/* Example main program that uses the functions in seval.h      */
/* to implement a read-eval-print loop to the terminal. sl_Init */
/* and sl_Eval_Str are the two routines from seval.h.           */
/* Note that we don't include                                   */
/* a newline in our prompt, since the slisp return	        */
/* values always end with a newline anyhow, following           */
/* the convention used in other xlisp routines.                 */

main()
{
    char inbuf[ BUF_SIZ ];
    sl_Init();
    for (;;) {
        int   got_err;
        char* result, *out;
        /* Read string to evaluate from user: */
        printf("> ");
        fgets( inbuf, BUF_SIZ, stdin );
	/* Evaluate the string: */
  	out = sl_Eval_Str(&got_err, &result, inbuf );
	/* If out != result then the evaluated      */
	/* function printed some output before      */
	/* returning, as for example from a PRINT   */
	/* or FORMAT function call		    */
	if (out != result) printf("%s", out);
	/* If an error was returned by slisp        */
	/* got_err will be true. The error messages */
	/* are not prepended by "error: " because   */
	/* some programs may not want this. But to  */
	/* be consistent with slisp conventions the */
	/* error message should be prepended with   */
	/* error:				    */
	/* If an error was not received then result */
	/* has the string equivalent of the value   */
	/* returned by the function		    */ 
	if (got_err)
	  printf("error: %s", result);
	else
	  printf("%s", result);
    }
}


Go to the first, previous, next, last section, table of contents.