[Cffi-devel] Help perfecting my GC finalizer/constructor

Willem Rein Oudshoorn woudshoo at xs4all.nl
Sun Apr 20 15:13:37 UTC 2014


Joeish W <joeish80829 at yahoo.com> writes:

> 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
>
>  (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))
>
> When I run the make-cvmatrix function to create a matrix  it outputs a
> struct instead of a pointer like i needed. ...

You really do not want to return a pointer.  For (at least) two reasons:

1 - It will make it much harder to use the functions in lisp because you
    do need to remember what they point to.

2 - It prevents automatic garbage collection of the underlying C
    objects.

However, if you really want to use direct C-pointers, the code is not
ok, see below:

> ... I changed the last line of
> the make-cvmatrix function to be "sap"  as below:
>
>     (tg:finalize matrix (lambda (x) (del-mat sap)))
>     sap))
>
> ...and it appears to run poorly with only major 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.

No this change is NOT ok.  Remember the tg:finalize will make sure that
the code

  (del-mat sap)

is called when 'matrix' is garbage collector.

In the first version, the function returned matrix and as long as matrix
is alive, the del-mat is not callled.

In the second version, you do not return 'matrix' and as soon as the sap
is returned, the 'matrix' is eligible for garbage collection and
therefore you will get random crashes because the '(del-mat sap)' will
be called while you are still using the returned SAP.

NOTE:  The original code is WRONG, the lambda in 'tg:finalize' should
NOT take any arguments so the original line should read

  (tg:finalize matrix (lambda () (del-mat-sap)))

> 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 :

Ok, here is some code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Tell CFFI of the existence of the 'Mat' C-type.
;;;
;;; This can be used as:
;;;
;;;   - %cv-mat  -- Which will not enable garbage collection of the C-mat.
;;;   - (%cv-mat :garbage-collect t) -- Which will enable garbage collection.

(define-foreign-type cv-mat ()
  ((garbage-collect  :reader garbage-collect :initform nil :initarg :garbage-collect))
  (:actual-type :pointer)
  (:simple-parser %cv-mat))


;;; Define the Lisp object corresponding to the 'Mat' C-Type

(defclass cv-matrix ()
  ((c-pointer :reader c-pointer :initarg :c-pointer)))

;;; Translation between C pointers to the lisp cv-matrix

(defmethod translate-to-foreign ((lisp-value cv-matrix) (c-type cv-mat))
  (c-pointer lisp-value))


(defmethod translate-from-foreign (c-pointer (c-type cv-mat))
  (let ((matrix  (make-instance 'cv-matrix :c-pointer c-pointer)))
    (when (garbage-collect c-type)
      (tg:finalize matrix (lambda () (del-mat c-pointer))))
    matrix))

;;; C functions

(defcfun ("cv_delete_Mat" del-mat) :void
  (ptr %cv-mat))

(defcfun ("cv_create_Mat" create-mat) (%cv-mat :garbage-collect t))

(defcfun ("cv_create_Mat_typed" create-mat-typed) (%cv-mat :garbage-collect t)
  (rows :int)
  (cols :int)
  (type :int))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

>
> (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.

I do no understand what you mean here.  

Wim Oudshoorn





More information about the cffi-devel mailing list