CFFIを使う
CFFIとは
Common Lispと外部ライブラリを連携させるライブラリです。
http://common-lisp.net/project/cffi/
主な用途は、
- 多くの処理系でサポートされているのでコードの移植性が高まる
- dllやsoといった外部ライブラリを読み込む
- Common Lisp外の関数や変数(ポインタ、文字列)などを扱う
どうしてCFFIが必要なのか
そもそもCommon Lispにはcompile*1もcompile-file*2もあるので多くの処理系がネイティブで実行できます。さらに、compiler-macro*3やdeclare*4があるので、Common Lisp内で簡潔していれば非常に最適化も優秀です。
なので、dll*5やso*6を利用すると外部インターフェースを経由したやり取りになるので、高速化のボトルネックになってしまいます。
それでもCFFIを使わなければならない状況は多いわけです。
例えば、処理系が動作しているOS向けアプリケーションを作成しようとすると、
OSのAPIを利用しなければならないですが、現在主流なOSはCommon Lisp向けのAPIを提供していないでしょう*7。
つまりAPIを実装する必要があるのですが、その橋渡しになるのがCFFIです。
CFFIのインストール
いつも通りQuicklispでインストールできます。
(ql:quickload :cffi)
使い方
CFFIを利用できるパッケージを準備する
CFFIを利用するときは主にライブラリのAPIラッパー作成なので、
ラッパー用のパッケージを生成したほうが良いでしょう。
common-lisp-user直下で作業するには不向きでしょう。
(defpackage :foreign-library (:use :cl :cffi)) (in-package :foreign-library)
外部ライブラリを定義する
外部ライブラリを使用する場合は、ライブラリ定義を行います。
ライブラリ定義では、プラットフォーム毎のライブラリ名や
ライブラリファイルの優先順序などを定義します。
(define-foreign-library foreign-library (:unix (:default "libforeign-library")) (:windows (:default "ForeignLibrary"))) (use-foreign-library foreign-library)
外部の関数を定義する
外部の関数を使いたい場合、そのインタフェースを定義する必要があります。
(defcfun ("foreign-function-name" function-symbol) :return-value-type (arg1 :arg-value-type) ...)
通常の関数定義に定義していきますが、
外部の関数なので、関数名はシンボルではなく文字列で、
返り値と引数には外部型情報を与える必要があります。
あとはfunction-symbolに外部関数インタフェースが束縛されるので、
通常の関数同様に呼び出すことができます。
(foreign-symbol 0)
まとめ
CFFIを利用することでマルチプラットフォームな外部ライブラリラッパーを実装することができます。
これで、Common Lispの外の世界とも仲良くやっていけるわけですね。