April 14th, 2012


CFFI now has (on the master branch, but not yet in quicklisp) the system cffi-libffi, which allows calling and returning structures by value. For example, in the GSL library, complex numbers and functions are defined passing and returning the complex structures by value, so we can define
    (cffi:defcstruct (complex-double-c :class complex-double-type)
      (dat :double :count 2))

    (defmethod cffi:translate-into-foreign-memory ((value complex) (type complex-double-type) p)
      (cffi:with-foreign-slots ((dat) p (:struct complex-double-c))
        (setf (cffi:mem-aref dat :double 0) (realpart value)
    	  (cffi:mem-aref dat :double 1) (imagpart value))))

    (defmethod cffi:translate-from-foreign (p (type complex-double-type))
      (cffi:with-foreign-slots ((dat) p (:struct complex-double-c))
        (complex (cffi:mem-aref dat :double 0)
    	     (cffi:mem-aref dat :double 1))))

    (cffi:define-foreign-library libgslcblas
      (:unix (:or "libgslcblas.so.0" "libgslcblas.so"))
      (t (:default "libgslcblas")))

    (cffi:define-foreign-library libgsl
      (:unix (:or "libgsl.so.0" "libgsl.so"))
      (t (:default "libgsl")))

    (cffi:use-foreign-library libgslcblas)
    (cffi:use-foreign-library libgsl)

    (defun complex-log (c)
       (cffi:foreign-funcall "gsl_complex_log"
        (:struct complex-double-c) c (:struct complex-double-c)))

and then find
   (complex-log #C(1.0d0 2.0d0))
   #C(0.8047189562170501d0 1.1071487177940904d0)

Note that there are changes that affect CFFI users even if they don't load cffi-libffi; using bare structure names foo insead of (:struct foo) or :pointer or (:pointer (:struct foo)) will trigger a style warning, and there is a new function mem-aptr that does for structure arrays what mem-aref does when the bare structure names are used. Please try it and report issues on cffi-devel. Thank you.

Note: the old system FSBV, which did what cffi-libffi does but in a clumsier way, is now obsolete and will not work with this version of CFFI.