外部モジュールの呼び出し
clispでCの関数を呼ぶ方法。
概要
clispでCの関数を呼ぶには、FFI(Foregin Language Interface)を使う方法と、External Moduleを使う方法がある。
ドキュメントから特徴を抜粋すると、
Extenal Module | FFI | 備考 | |
---|---|---|---|
速度 | ○ | × | |
移植性 | ○ | × | FFIはすべてのclisp環境で使えるわけではない |
サイズ | × | ○ | |
インターフェイス | ○ | × | FFIでは&optionalとかは使えない |
で、今回使うのはExteranl Moduleのほう。
ディレクトリの準備
まず、カレントディレクトリにlinkkit/へのシンボリックリンクを作る。
この中には、clisp.hなどモジュールを作るのに必要・便利なツールが入っている。
このディレクトリはlink setと呼ばれる。
$ ln -s /opt/local/lib/clisp/linkkit/ . $ ls linkkit@
次にmodule setと呼ばれるディレクトリを作る。
これは、clisp-linkに自動生成してもらう。
$ sh /opt/local/lib/clisp/clisp-link create-module-set test $ ls linkkit@ test/ $ ls test Makefile link.sh
コーディング
module setの中にtest.cを作って、適当なコードを書く。
ここはまだ、詳しく調べいない。
// test/test.c #include<stdio.h> #define COMPILE_STANDALONE #include "clisp.h" DEFMODULE(test,"TEST") DEFUN(TEST::MSG,){ printf("hello\n"); }
あと、Makefileをちょっといじくる。
特に、test.cはそのままではCのコードにならないので、linkkit/modprep.lispでCのコードに変換してやる必要がある。
# test/Makefile # Makefile for CLISP module set test CC = CPPFLAGS = CFLAGS = INCLUDES= ../linkkit MODPREP=../linkkit/modprep.lisp CLISP = SHELL = /bin/sh clisp-module : test.o test.o : test.m.c gcc -I$(INCLUDES) -o test.o -c test.m.c test.m.c : test.c clisp $(MODPREP) test.c
間違った記述をしていないかを確かめるため、このあたりで一回makeしておく。
$ cd test $ make clisp ../linkkit/modprep.lisp test.c ;; MODPREP: "test.c" --> #P"test.m.c" ;; MODPREP: reading "test.c": 130 bytes, 8 lines ;; MODPREP: 0 objects, 1 DEFUN ;; packages: ("TEST") MODPREP: wrote test.m.c (1,860 bytes) gcc -I../linkkit -o test.o -c test.m.c $
モジュールの作成
あとは、定義した関数をclispから使えるようにすればいい。
まず、モジュールを定義するlispのコードを準備する。
あと、clispのためのインターフェイスをいくつか用意する。
;; test.lisp (defpackage #:test (:use #:common-lisp) (:export #:msg))
;; preload.lisp (make-package "TEST")
そして、link.shを修正する。
file_list='test.o' mod_list='test' make clisp-module CC="${CC}" CPPFLAGS="${CPPFLAGS}" \ CFLAGS="${CFLAGS}" INCLUDES="$absolute_linkkitdir" NEW_FILES="$file_list" NEW_LIBS="$file_list" NEW_MODULES="$mod_list" TO_LOAD='test' TO_PRELOAD="preload.lisp"
そのあと、clisp-linkでモジュールを作成する。
$ ls linkkit@ test/ $ sh /opt/local/lib/clisp/clisp-link add-module-set test \ /opt/local/lib/clisp/base base+test $ ls base+test/ linkkit@ test/
あとはちゃんと動くかチェックする。
$ clisp -K $PWD/base+test [1]> (test:msg) hello (TEST:MSG); NIL [2]>