The Common Lisp Cookbook – 外部関数インターフェイス

Table of Contents

The Common Lisp Cookbook – 外部関数インターフェイス

📢 🎓 ⭐ Learn Common Lisp efficiently in videos, by the Cookbook's main contributor. Learn more.

🖊️ Discover a new Common Lisp and Coalton editor for beginners: mine and a new VSCode extension for Common Lisp: OLIVE.

ANSI Common Lisp 標準はこの話題に触れていません。そのため、ここで言えることのほとんどは OS と実装に依存します。しかし現在では、移植性があり使いやすい C 外部関数インターフェイスである CFFI ライブラリを使えます。

CFFI、Common Foreign Function Interface は、Common Lisp 向けの移植可能な FFI であることを目指しています。さまざまな Common Lisp 実装のネイティブ FFI の API の違いを抽象化します。

すぐに例を見てみましょう。

CFFI: math.h ヘッダファイルの C 関数を呼び出す

defcfun を使って、math.h の外部 C 関数 ceil とインターフェイスします。

defcfun は cffi ライブラリのマクロで、指定した名前の関数を生成します。

CL-USER> (cffi:defcfun ("ceil" c-ceil) :double (number :double))

“ceil” という C 関数を Lisp 側では “c-ceil” と呼び、引数を1つ取り、それは double float で、戻り値も double float の数値である、と指定しています。

上の関数を macrostep-expand でマクロ展開すると次のようになります。

(progn
  nil
  (defun c-ceil (number)
    (let ((#:g312 number))
      (cffi-sys:%foreign-funcall "ceil" (:double #:g312 :double) :convention
				 :cdecl :library :default))))

ceil ではなく c-ceil と呼んだ理由は、これは C のラッパーだとわかるようにするための、この例だけの都合です。組み込みの Common Lisp 関数やマクロを指す名前ではないので、”ceil” という名前にしてもかまいません。

math.h 由来の c-ceil 関数ができたので、使ってみましょう。double float を渡す必要があります。

CL-USER> (c-ceil 5.4d0)
6.0d0

見てのとおり、動きます。期待どおり double が 6.0d0 に切り上げられました。

もう1つ試してみましょう。今度は floor を使います。この Common Lisp 関数はすでに存在するため、”floor” とは名付けられませんでした。

CL-USER> (cffi:defcfun ("floor" c-floor) :double (number :double))
C-FLOOR
CL-USER> (c-floor 5d0)
5.0d0
CL-USER> (c-floor 5.4d0)
5.0d0

いいですね。

もう1つ、引き続き double float で math.h の sqrt を試しましょう。

CL-USER> (cffi:defcfun ("sqrt" c-sqrt) :double (number :double))
C-SQRT
CL-USER> (c-sqrt 36.50d0)
6.041522986797286d0

新しい c-sqrt を使って算術演算もできます。

CL-USER> (+ 2 (c-sqrt 3d0))
3.732050807568877d0

新しく輝く c-sqrt を使って double のリストを map し、すべての平方根を取ることさえできます。

CL-USER> (mapcar #'c-sqrt '(3d0 4d0 5d0 6d0 7.5d0 12.75d0))
(1.7320508075688772d0 2.0d0 2.23606797749979d0 2.449489742783178d0
 2.7386127875258306d0 3.570714214271425d0)

Page source: ja/ffi.md

T
O
C