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: VxWorks Up: システム関数 Previous: Cで書かれたLisp関数の追加

他言語インターフェース

Euslispとのリンクを考慮していないCの関数もEuslispにロードすることができる。 これらの関数は、他言語関数と呼ばれる。 そのようなプログラムはload-foreignマクロによりロードされる。 そのマクロは、foreign-moduleのインスタンスを返す。 オブジェクトファイルの中の外部symbol定義は、モジュールオブジェクトの中に 登録されている。 defforeignは、Euslispから呼び出すための C関数に対するエントリーを作るために使用される。 defun-c-callableは、Cから呼び出し可能なlisp関数を定義する。 呼び出し可能なCの関数は、パラメータを変換し関連するEuslispの関数へ制御を移すために pod-codeと呼ばれる特別なコードを持つ。 pod-addressは、この特別なコードのアドレスを返す。 そのアドレスはCの関数に通知されるべきである。

これは、Cのプログラムのサンプルと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

Euslispのデータ表現は、以下に示す方法でCのデータ表現に変換される。 EusLispの30ビット整数(文字列を含む)は、符号拡張され、スタックを通してCの関数に渡される。 30ビット実数は、倍精度実数(double)に拡張され、スタックを通して渡される。 文字列と整数ベクトルと実数ベクトルについては、その最初の要素のアドレスのみが スタックに渡され、行列自体はコピーされない。 Euslispには、2次元以上の配列を渡す方法がない。 2次元以上の配列はすべての要素を線形に保持する1次元ベクトルを持つ。 このベクトルは、array-entityマクロにより得られる。 もし、2次元行列をFORTRANのサブルーチンに送る場合、FORTRANにおいて列と行が反対となっているため その行列を転置しなければならないことに注意すること。

実数のEuslisp表現は、いつも単精度であるので、倍精度の実数のベクトルに渡すとき変換を要する。 変換関数、double2floatfloat2doubleは、この目的でclib/double.cの中に定義されている。 例えば、もし3x3の実数行列があり、CFのいう名のCの関数にそれを倍精度実数の行列として渡したいなら、 以下のように使用すればよい。

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

Cの構造体は、defstructマクロにより定義することができる。 defstructは、次のようなフィールド定義書式によりstruct-nameを受け取る。

     (defcstruct <struct-name>
        {(<field> <type> [*] [size])}*)
たとえば、以下に示す構造体の定義は、つぎのdefstructによって表現される。
     /* 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) [マクロ]

(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 [マクロ]

  defun-c-callable funcname paramspec resulttype . body [マクロ]   pod-address funcname [関数]
  • defun-c-callableで定義されたCで呼び出し可能なLisp関数funcnameにおける 他言語とEuslispとのインターフェースコードのアドレスを返す。 これは、他言語プログラムにLisp関数の位置を知らせるために使用される。
  array-entity array-of-more-than-one-dimension [マクロ]
  • 多次元配列の要素を保持する1次元ベクトルを返す。 これは、多次元あるいは一般の配列を他言語に渡すために必要である。 しかし、1次元のベクトルは直接渡すことができる。
  float2double float-vector [doublevector] [関数]
  • float-vectorを倍精度実数の表現に変換する。 その結果は、float-vectorであるが、最初の引き数の長さの2倍になっている。
  double2float doublevector [float-vector] [関数]
  • 倍精度実数表現が単精度のfloat-vectorに変換される。



Hirofumi Nakagaki
Fri Mar 22 14:04:29 JST 1996