Cで書かれたLisp関数の追加

ファイルに含まれるCを重く参照したり、行列にしばしばアクセスするような プログラムにおいては、Euslispで記述するよりはむしろCあるいは他の言語で 記述した方が効率が良く、記述もわかり易い。 EusLispは、Cで書かれたプログラムをリンクする方法を備えている。

もしCで書かれたEuslispの関数を定義したいならば、 Euslispで呼び出しできるCの関数はそれぞれ、3つの引き数を受けるように書かれなければ ならない。環境へのポインタと受け取る引き数の数とlispの引数領域を示す ポインタの3つである。 これらの引数は、c/eus.hの中のマクロによって参照されるため、 ctx, n, argvと名付けられねばならない。 Cのプログラムは、*eusdir*/c/eus.hをincludeしなければならない。 プログラマーは、そこに書かれた型やマクロに精通していなければならない。 エントリ関数名には、ソースファイルのbasenameを付けなければならない。

任意の数の実数の算術平均を計算するCの関数AVERAGEのサンプルコードは、 以下に示す通りである。 この例において、引数から実数値を得る方法、実数のポインタを作る方法、 特殊変数AVERAGEにポインタを設定する方法やエントリ関数aveに 関数やsymbolを定義する方法を知ることができる。 'cc -c -Dsun4 -DSolaris2 -K pic'でこのプログラムをコンパイルする。 c/eus.h内の正しい定義を選択するために、-Dsun4-DSolaris2 が必要である。 -K picは、ロード可能な共有オブジェクトのために、位置に依存するコードを Cコンパイラで生成させるために必要である。 その後、コンパイルの結果である'.o'ファイルがEuslispにロードすることができる。 もっと完全な例は*eusdir*/clib/*.cに置かれている。 これらの例は、ここで書かれた方法で定義され、ロードされる。

/* ave.c */
/* (average &rest numbers) */
#include "/usr/local/eus/c/eus.h"
static pointer AVESYM;
pointer AVERAGE(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ register int i;
  float sum=0.0, a, av;
  pointer result;
  numunion nu;
  for (i=0; i<n; i++) {
    a=ckfltval(argv[i]);
    sum += a;} /*get floating value from args*/
  av=sum/n;
  result=makeflt(av);
  AVESYM->c.sym.speval=result;  /*kindly set the result in symbol*/
  return(result);}

ave(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ char *p;
  p="AVERAGE";
  defun(ctx,p,argv[0],AVERAGE);
  AVESYM=intern(ctx,p,strlen(p),userpkg); /* make a new symbol*/
  }



2016-04-05