CFFI, the Common Foreign Function Interface, purports to be a portable FFI for Common Lisp. It abstracts away the differences between the API of the native FFIâs of the various Common Lisp implementations.
Weâll see an example right now.
CFFI: calling a C function from the math.h
header file.
Letâs use defcfun
to interface with the foreign ceil C function from math.h
.
defcfun is a macro in the cffi library that generates a function with the name you give it.
CL-USER> (cffi:defcfund ("ceil" c-ceil) :double (number :double))
We say that the âceilâ C function will be called âc-ceilâ on our Lisp side, it takes one argument that is a double float, and it returns a number that is also a double float.
Here is the above function macroexpanded with macrostep-expand
:
(progn
nil
(defun c-ceil (number)
(let ((#:g312 number))
(cffi-sys:%foreign-funcall "ceil" (:double #:g312 :double) :convention
:cdecl :library :default))))
The reason we called it c-ceil
and not ceil
is only for the example, so we know this is a wrapper around C. You can name it âceilâ, since it doesnât designate a built-in Common Lisp function or macro.
Now that we have a c-ceil function from math.h
, letâs use it! We must give it double float.
CL-USER> (c-ceil 5.4d0)
6.0d0
As you can see, it works! The double gets rounded up to 6.0d0
as expected.
Letâs try another one! This time, weâll use floor, and we couldnât name it âfloorâ because this Common Lisp function exists.
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
Great!
One more, letâs try sqrt
from math.h, still with double floats:
CL-USER> (cffi:defcfun ("sqrt" c-sqrt) :double (number :double))
C-SQRT
CL-USER> (c-sqrt 36.50d0)
6.041522986797286d0
We can do arithmetic with our new c-sqrt
:
CL-USER> (+ 2 (c-sqrt 3d0))
3.732050807568877d0
We can even use our new shiny c-sqrt
to map over a list of doubles and take the square root of all of them!
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: ffi.md