[cffi-devel] Support for cleanup actions on arguments performed when callback returns

Kalyanov Dmitry kalyanov.dmitry at gmail.com
Sun Jul 26 21:06:59 UTC 2009


I am trying to create a binding for gobject library with CFFI.

CFFI works extremely well, however I have a use case that is not covered by 
CFFI.

Basically, I want to define foreign types that should "clean up" after 
themselves when they are used as types for callback arguments.

I have following use cases for this:
1) I want to have a structure created when callback is entered and have its 
contents copied to foreign structure when callback returns.

2) I want to have wrappers that contain a pointer to foreign structure. 
However, I want to ensure that operations on wrapper signal errors when 
callback returns (because pointer points to a stack-allocated structure). This 
is needed to ensure that no operations are done on invalid pointer.

The attached patch provides suggested change: foreign types may specify that 
additional actions should be performed when the callback returns. This is 
achieved by adding new generic function CLEANUP-TRANSLATED-OBJECT-FOR-
CALLBACK. Additional generic function HAS-CALLBACK-CLEANUP is called at 
macroexpansion time as an optimization to remove unnecessary calls to CLEANUP-
TRANSLATED-OBJECT-FOR-CALLBACK.

Attached is a test case that demonstrates the usage and checks for correctness 
of behavior.

If there are obstacles for adding this patch, I would be happy to work on 
them.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: callback-cleanup.patch
Type: text/x-patch
Size: 3313 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/cffi-devel/attachments/20090727/df733dce/attachment.bin>
-------------- next part --------------
(defpackage :cffi-test-case
  (:use :cl :cffi)
  (:export :test))

(in-package :cffi-test-case)

(defcstruct gdk-rectangle-cstruct
  (x :int)
  (y :int)
  (width :int)
  (height :int))

(defstruct gdk-rectangle
  (x 0)
  (y 0)
  (width 0)
  (height 0))

(define-foreign-type gdk-rectangle-type ()
  ()
  (:actual-type :pointer)
  (:simple-parser gdk-rectangle))

(defmethod translate-to-foreign (rectangle (type gdk-rectangle-type))
  (let ((native-structure (foreign-alloc 'gdk-rectangle-cstruct)))
    (loop
       for slot in '(x y width height)
       do (setf (foreign-slot-value native-structure 'gdk-rectangle-cstruct slot)
                (slot-value rectangle slot)))
    (values native-structure rectangle)))

(defmethod free-translated-object (native-structure (type gdk-rectangle-type) rectangle)
  (loop
     for slot in '(x y width height)
     do (setf (slot-value rectangle slot)
              (foreign-slot-value native-structure 'gdk-rectangle-cstruct slot)))
  (foreign-free native-structure))

(defmethod has-callback-cleanup ((type gdk-rectangle-type))
  t)

(defmethod translate-from-foreign (native-structure (type gdk-rectangle-type))
  (let ((rectangle (make-gdk-rectangle)))
    (loop
       for slot in '(x y width height)
       do (setf (slot-value rectangle slot)
                (foreign-slot-value native-structure 'gdk-rectangle-cstruct slot)))
    rectangle))

(defmethod cleanup-translated-object-for-callback ((type gdk-rectangle-type) rectangle native-structure)
  (loop
     for slot in '(x y width height)
     do (setf (foreign-slot-value native-structure 'gdk-rectangle-cstruct slot)
              (slot-value rectangle slot))))

(defcallback incf-rectangle-callback :void
    ((rectangle gdk-rectangle) (delta :int))
  (loop
     for slot in '(x y width height)
     do (incf (slot-value rectangle slot) delta)))

(defun incf-rectangle (r &optional (delta 1))
  (foreign-funcall-pointer (callback incf-rectangle-callback) ()
                           gdk-rectangle r
                           :int delta
                           :void))

(defun test ()
  (let ((r (make-gdk-rectangle :x 1 :y 2 :width 3 :height 4)))
    (print r)
    (incf-rectangle r 3)
    (print r)
    (and (= 4 (gdk-rectangle-x r))
         (= 5 (gdk-rectangle-y r))
         (= 6 (gdk-rectangle-width r))
         (= 7 (gdk-rectangle-height r)))))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <https://mailman.common-lisp.net/pipermail/cffi-devel/attachments/20090727/df733dce/attachment.sig>


More information about the cffi-devel mailing list