Best way to do GC in Lisp/CFFI

Discussion of Common Lisp

Best way to do GC in Lisp/CFFI

Postby joeish80829 » Wed Apr 09, 2014 8:43 pm

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:

Code: Select all
Mat* cv_create_Mat() {
    return new Mat();

Code: Select all
void cv_delete_Mat(void* ptr) {
    delete (~Mat*)ptr;

Here are the Lisp wrappers for them:
Code: Select all
(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

Code: Select all
(dotimes (n 1000)
(setf m (mat))
(del-mat m))
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

Re: Best way to do GC in Lisp/CFFI

Postby marcoxa » Thu Apr 10, 2014 12:11 pm

Another way to do it (gc on the C++ side) is to link in the Bohem GC and stop worrying.

Marco Antoniotti
Posts: 85
Joined: Thu Aug 14, 2008 6:31 pm

Re: Best way to do GC in Lisp/CFFI

Postby nuntius » Thu Apr 10, 2014 3:52 pm

You probably heard about "finalizers".
Here's a couple top links on the subject.

Finalizers involve some interesting tradeoffs.
C/C++ libraries are often written assuming strict, often lexically-scoped object lifecycles.
Finalizers hook into looser GC semantics.
The order of invocation is undefined for finalizers, and the GC may not even call them before program exit.
I'm undecided whether finalizers are a net win, but they definitely have some proponents.
User avatar
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Best way to do GC in Lisp/CFFI

Postby joeish80829 » Fri Apr 11, 2014 10:07 am

Thanks for your replies to my question, I was planning to go the trivial-garbage route and someone from CFFI-DEVEL kindly gave me this code to do GC automatically using my mat and del-mat functions

Code: Select all
 (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)))

When I run the make-cvmatrix function to create a matrix it outputs a struct instead of a pointer like i needed. I changed the last line of the make-cvmatrix function to be "sap" as below:

Code: Select all
    (tg:finalize matrix (lambda (x) (del-mat sap)))

...and it appears to run fine with only minor variations in my ram levels which i suppose is just a result of lisps GC in process.
Since I'm new to GC w/ trivial-garbage, I was hoping someone can verify first that the change to sap was an ok move.

I was hoping someone could edit my code so I have a good example of Lisp GC with TG to work from and if I write a defcfun for this C wrapper :

Code: Select all
Mat* cv_create_Mat_typed(int rows, int cols, int type) {
    return new Mat(rows, cols, type);


(defcfun ("cv_create_Mat_typed" mat-typed)  (:pointer mat)
  "MAT constructor with a row, column and type parameter."
  (rows :int)
  (cols :int)
  (type :int))

show me where the rows cols type params get placed in an edited finalizer/constructor above..I would definately appreciate greatly:), concrete examples using the code I posted.
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 11 guests