[Cffi-devel] What is the proper way to do GC in CFFI

Martin Simmons martin at lispworks.com
Fri Apr 11 10:53:01 UTC 2014


I think it is better to avoid garbage collection of foreign objects because it
is too easy to introduce use-after-free errors if you pass the foreign object
to foreign code.  Also, finalizers interact poorly with generational GC.

The simplest way to solve the original problem is to implement a macro that
allocates and frees the object, e.g. with-temporary-mat

(defmacro with-temporary-mat (mat &body body)
  (let ((m (gensym "mat")))
    `(let ((,m (mat)))
       (unwind-protect
           (let ((,mat ,m))
             , at body)
         (del-mat ,m)))))

__Martin


>>>>> On Fri, 11 Apr 2014 08:59:20 +0200, Stephan Frank said:
> 
> Hi Joeish,
> 
> have a look at trivial-garbage (
> http://common-lisp.net/project/trivial-garbage/). This project wraps the
> finalizers of different Lisp implementations with a common interface.
> 
> So in your case it is best to wrap the pointer in a Lisp struct and attach
> that the finalizer like this (not tested, so syntax errors may apply). You
> can remove the type annotation of the struct slot if you don't want any
> SBCL-specific code.
> 
> (defstruct (cvmatrix (:constructor %make-cvmatrix))
>   (sap (mat) :type sb-sys:system-area-pointer :read-only t))
> 
> (defun make-cvmatrix ()
>   (let* ((matrix (%make-cvmatrix))
>          (sap (cvmatrix-sap matrix)))
>     (tg:finalize matrix (lambda (x) (del-mat sap)))
>     matrix))
> 
> 
> Now you create matrices with make-cvmatrix which returns you a cvmatrix
> struct. Whenever this returned struct is garbage collected the finalizer is
> called.
> If you prefer classes to structs, of course a similar approach with
> make-sintance and after methods can be easily implemented.
> 
> Regs,
> Stephan
> 
> 
> 
> 2014-04-10 5:41 GMT+02:00 Joeish W <joeish80829 at yahoo.com>:
> 
> > I have Lisp functions that wrap C wrappers for C++ functions that contain
> > a new operator. The C wrappers have to stay the same I can't change those
> > but I was advised to update my method of GC.
> >
> > Here are the C wrappers:
> >
> > Mat* cv_create_Mat() {
> >     return new Mat();
> > }
> >
> > void cv_delete_Mat(void* ptr) {
> >     delete (~Mat*)ptr;
> > }
> >
> > Here are the Lisp wrappers for them:
> >
> > (defcfun ("cv_create_Mat" mat) (:pointer mat)
> >   "MAT constructor")
> >
> > (defcfun ("cv_delete_Mat" del-mat) :void
> >   (ptr :pointer))
> >
> > In a loop, as below, I would normally after calling a MAT function, delete
> > it when I'm done with it manually with DEL-MAT, but I heard there was a
> > better way by actually entering in the DEL-MAT function into Lisps natural
> > GC methods so it would know when it comes across a function with a new it
> > should call delete to get rid of it when it know i'm done with it.. The
> > thing is I could use help to get started.  Hopefully a concrete example of
> > how to do this so I don't have to call DEL-MAT manually
> >
> > (dotimes (n 1000)
> > (setf m (mat))
> > (del-mat m))
> >
> > _______________________________________________
> > Cffi-devel mailing list
> > Cffi-devel at common-lisp.net
> > http://common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel
> >
> >
> 




More information about the cffi-devel mailing list