National Institute of Advanced Industrial Science and Technology (AIST) This page is a page of the former research institute. We stopped updating on March 31.2001.
E-mail to webmaster (Japanese) E-mail to webmaster (English)
next up previous contents index
Next: Multithread Up: System Functions Previous: Adding Lisp Functions Coded

Foreign Language Interface

Functions written in C without concern about linking with EusLisp can be loaded onto EusLisp, too. These functions are called foreign functions. Such programs are loaded by load-foreign macro which returns an instance of foreign-module. External symbol definitions in the object file is registered in the module object. Defforeign is used to make entries to C functions to be called from EusLisp. Defun-c-callable defines lisp functions callable from C. C-callable functions have special code piece called pod-code for converting parameters and transferring control to the corresponding EusLisp function. Pod-address returns the address of this code piece which should be informed to C functions.

Here is an example of C program and its interface functions to EusLisp.

/* C program named cfunc.c*/

static int (*g)();	/* variable to store Lisp function entry */

double sync(x)
double x;
{ extern double sin();
  return(sin(x)/x);}

char *upperstring(s)
char *s;
{ char *ss=s;
  while (*s) { if (islower(*s)) *s=toupper(*s); s++;}
  return(ss);}

int setlfunc(f)      /* remember the argument in g just to see */
int (*f)();          /* how Lisp function can be called from C */
{ g=f;}

int callfunc(x)      /* apply the Lisp function saved in g to the arg.*/
int x;
{ return((*g)(x));}

;;;; Example program for EusLisp's foreign language interface
;;;; make foreign-module
(setq m (load-foreign "cfunc.o"))

;; define foreign functions so that they can be callable from lisp
(defforeign sync m "sync" (:float) :float)
(defforeign toupper m "upperstring" (:string) :string)
(defforeign setlfunc m "setlfunc" (:integer) :integer)
(defforeign callfunc m "callfunc" (:integer) :integer)

;; call them
(sync 1.0)	--> 0.841471
(print (toupper "abc123"))  --> "ABC123"

;; define a test function which is callable from C.
(defun-c-callable TEST ((a :integer)) :integer
      (format t "TEST is called, arg=~s~%" a)
      (* a a))    ;; return the square of the arg
;;  call it from C
;;setlfunc remembers the entry address of Lisp TEST function.
(setlfunc (pod-address (intern "TEST")))
(callfunc 12)  --> TEST is called, arg=12  144

Data representations in EusLisp are converted to those of C in the following manners: EusLisp's 30-bits integer (including character) is sign-extended and passed to a C function via stack. 30-bit float is extended to double and passed via stack. As for string, integer-vector and float-vector, only the address of the first element is passed on the stack, and the entire array remains uncopied. A string always has a null code at the end. EusLisp does not know how to pass arrays of more than one dimension. Every array of more than one dimension has one dimensional vector that holds all the elements linearly. This vector is obtained by array-entity macro. Also, note that a two-dimensional matrix should be transposed if it is sent to the FORTRAN subroutines, since rows and columns are ordered oppositely in FORTRAN.

Since EusLisp's representation of floating-point numbers is always single precision, conversion is required when you pass a vector of double precision floating point numbers. The conversion functions, double2float and float2double are provided for this purpose in clib/double.c. For an instance, if you have a 3x3 float-matrix and wish to pass it to a C function named CF as a matrix of double, use the following forms.

     (setq mat (make-matrix 3 3))
     (CF (float2double (array-entity mat)))

Struct in C can be defined by the defcstruct macro. Defcstruct accepts struct-name followed by field definition forms.

     (defcstruct <struct-name>
        {(<field> <type> [*] [size])}*)
For example, following struct definition is represented by the next defcstruct.
     /* C definition */
     struct example {
        char  a[2];
        short b;
        long  *c;
        float *d[2];};

     /* equivalent EusLisp definition */
     (defcstruct example
        (a :char 2)
        (b :short)
        (c :long *)
        (d :float * 2))

  load-foreign objfile &key symbol-input symbol-output (symbol-file objfile) ld-option) [macro]

(setq linpack-module
    (load-foreign "/usr/local/eus/clib/linpackref.o"
        :ld-option  "-L/usr/local/lib -llinpack -lF77 -lm -lc"
        :symbol-output "euslinpack"
        :symbol-file "euslinpack"
        ))
(unix:unlink "euslinpack")

  defforeign funcname module cname paramspec resulttype [macro]

  defun-c-callable funcname paramspec resulttype . body [macro]   pod-address funcname [function]
  • returns the address of a foreign-to-EusLisp interface code of the c-callable Lisp function funcname defined by defun-c-callable. This is used to inform a foreign language program of the location of a Lisp function.
  array-entity array-of-more-than-one-dimension [macro]
  • returns one-dimensional vector which holds all the elements of a multi-dimensional array. This is needed to pass a multi-dimensional or general array to a foreign function, although a simple vector can be passed directly.
  float2double float-vector [doublevector] [function]
  • converts a float-vector to double precision representation. The result is of type float-vector but the length is twice as much as the first argument.
  double2float doublevector [float-vector] [function]
  • A vector of double precision numbers is converted to single precision float-vector.


next up previous contents index
Next: Multithread Up: System Functions Previous: Adding Lisp Functions Coded

Hirofumi Nakagaki
Fri Mar 22 12:46:38 JST 1996