;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: ffi.lisp,v 1.22 2006/02/06 11:49:50 espen Exp $
+;; $Id: ffi.lisp,v 1.24 2006/02/19 19:17:45 espen Exp $
(in-package "GLIB")
(mapc #'funcall cleanup-arguments args)))))
-(defmacro defcallback (name (return-type &rest args) &body body)
- (let ((def-callback #+cmu'alien:def-callback
- #+sbcl'sb-alien:define-alien-function))
- `(,def-callback ,name
- (,(alien-type return-type)
- ,@(mapcar #'(lambda (arg)
- (destructuring-bind (name type) arg
- `(,name ,(alien-type type))))
- args))
- ,(to-alien-form
- `(let (,@(delete nil
- (mapcar #'(lambda (arg)
- (destructuring-bind (name type) arg
- (let ((from-alien
- (from-alien-form name type)))
- (unless (eq name from-alien)
- `(,name ,from-alien)))))
- args)))
- ,@body)
- return-type))))
-#+sbcl
-(defun callback (af)
- (sb-alien:alien-function-sap af))
+;;;; C callbacks
+
+(defmacro define-callback (name return-type args &body body)
+ (let ((define-callback
+ #+cmu'alien:def-callback
+ #+(and sbcl alien-callbacks)'sb-alien::define-alien-callback
+ #+(and sbcl (not alien-callbacks))'sb-alien:define-alien-function))
+ (multiple-value-bind (doc declaration body)
+ (cond
+ ((and (stringp (first body)) (eq (cadr body) 'declare))
+ (values (first body) (second body) (cddr body)))
+ ((stringp (first body))
+ (values (first body) nil (rest body)))
+ ((eq (caar body) 'declare)
+ (values nil (first body) (rest body)))
+ (t (values nil nil body)))
+ `(,define-callback ,name
+ #+(and sbcl alien-callbacks),(alien-type return-type)
+ (#+(or cmu (and sbcl (not alien-callbacks))),(alien-type return-type)
+ ,@(mapcar #'(lambda (arg)
+ (destructuring-bind (name type) arg
+ `(,name ,(alien-type type))))
+ args))
+ ,@(when doc (list doc))
+ ,(to-alien-form
+ `(let (,@(loop
+ for (name type) in args
+ as from-alien-form = (callback-from-alien-form name type)
+ collect `(,name ,from-alien-form)))
+ ,@(when declaration (list declaration))
+ (unwind-protect
+ (progn ,@body)
+ ,@(loop
+ for (name type) in args
+ do (callback-cleanup-form name type))))
+
+ return-type)))))
+
+(defun callback-address (callback)
+ #+cmu(alien::callback-trampoline callback)
+ #+(and sbcl (not alien-callbacks))(sb-alien:alien-function-sap callback)
+ #+(and sbcl alien-callbacks)(sb-alien:alien-sap callback))
#+sbcl
-(deftype callback () 'sb-alien:alien-function)
+(deftype callback ()
+ #-alien-callbacks'sb-alien:alien-function
+ #+alien-callbacks'sb-alien:alien)
+
+
+;;; These are for backward compatibility
+
+(defmacro defcallback (name (return-type &rest args) &body body)
+ `(define-callback ,name ,return-type ,args ,@body))
+
+#-cmu
+(defun callback (callback)
+ (callback-address callback))
+
+
;;;; Definitons and translations of fundamental types
(def-type-method from-alien-form (form))
(def-type-method cleanup-form (form)
"Creates a form to clean up after the alien call has finished.")
+(def-type-method callback-from-alien-form (form))
+(def-type-method callback-cleanup-form (form))
(def-type-method to-alien-function ())
(def-type-method from-alien-function ())
(def-type-method writer-function ())
(def-type-method reader-function ())
-(def-type-method weak-reader-function ())
(def-type-method destroy-function ())
(def-type-method unbound-value ()
(declare (ignore type args))
#'identity)
+(defmethod callback-from-alien-form (form (type t) &rest args)
+ (apply #'copy-from-alien-form form type args))
+
+(defmethod callback-cleanup-form (form (type t) &rest args)
+ (declare (ignore form type args))
+ nil)
+
(defmethod destroy-function ((type t) &rest args)
(declare (ignore type args))
#'(lambda (location &optional offset)
(defmethod copy-from-alien-function ((type t) &rest args)
(apply #'from-alien-function type args))
-(defmethod weak-reader-function ((type symbol) &rest args)
- (apply #'reader-function type args))
-
-
(defmethod alien-type ((type (eql 'signed-byte)) &rest args)
(declare (ignore type))
(destructuring-bind (&optional (size '*)) args
(destructuring-bind (&optional (size '*)) args
(let ((size (if (eq size '*) +bits-of-int+ size)))
(ecase size
- (8 #'(lambda (sap &optional (offset 0))
+ (8 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(signed-sap-ref-8 sap offset)))
- (16 #'(lambda (sap &optional (offset 0))
+ (16 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(signed-sap-ref-16 sap offset)))
- (32 #'(lambda (sap &optional (offset 0))
+ (32 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(signed-sap-ref-32 sap offset)))
- (64 #'(lambda (sap &optional (offset 0))
+ (64 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(signed-sap-ref-64 sap offset)))))))
(defmethod alien-type ((type (eql 'unsigned-byte)) &rest args)
(destructuring-bind (&optional (size '*)) args
(let ((size (if (eq size '*) +bits-of-int+ size)))
(ecase size
- (8 #'(lambda (sap &optional (offset 0))
+ (8 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-8 sap offset)))
- (16 #'(lambda (sap &optional (offset 0))
+ (16 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-16 sap offset)))
- (32 #'(lambda (sap &optional (offset 0))
+ (32 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-32 sap offset)))
- (64 #'(lambda (sap &optional (offset 0))
+ (64 #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-64 sap offset)))))))
(defmethod reader-function ((type (eql 'single-float)) &rest args)
(declare (ignore type args))
- #'(lambda (sap &optional (offset 0))
+ #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-single sap offset)))
(defmethod reader-function ((type (eql 'double-float)) &rest args)
(declare (ignore type args))
- #'(lambda (sap &optional (offset 0))
+ #'(lambda (sap &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-double sap offset)))
(defmethod reader-function ((type (eql 'base-char)) &rest args)
(declare (ignore type args))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(code-char (sap-ref-8 location offset))))
(defmethod reader-function ((type (eql 'string)) &rest args)
(declare (ignore type args))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(unless (null-pointer-p (sap-ref-sap location offset))
#+cmu(%naturalize-c-string (sap-ref-sap location offset))
#+sbcl(%naturalize-utf8-string (sap-ref-sap location offset)))))
(defmethod reader-function ((type (eql 'pathname)) &rest args)
(declare (ignore type args))
(let ((string-reader (reader-function 'string)))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(let ((string (funcall string-reader location offset)))
(when string
(parse-namestring string))))))
(defmethod reader-function ((type (eql 'boolean)) &rest args)
(declare (ignore type))
(let ((reader (apply #'reader-function 'signed-byte args)))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(not (zerop (funcall reader location offset))))))
(defmethod reader-function ((type (eql 'system-area-pointer)) &rest args)
(declare (ignore type args))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(sap-ref-sap location offset)))
(declare (ignore type args))
(alien-type 'pointer))
+#+nil
(defmethod size-of ((type (eql 'callback)) &rest args)
(declare (ignore type args))
(size-of 'pointer))
(defmethod to-alien-form (callback (type (eql 'callback)) &rest args)
(declare (ignore type args))
- #+cmu `(callback ,callback)
- #+sbcl `(sb-alien:alien-function-sap ,callback))
+ `(callback-address ,callback))
(defmethod to-alien-function ((type (eql 'callback)) &rest args)
(declare (ignore type args))
- #+cmu #'(lambda (callback) (callback callback))
- #+sbcl #'sb-alien:alien-function-sap)
+ #'callback-address)
+#+nil(
#+cmu
(defun find-callback (pointer)
(find pointer alien::*callbacks* :key #'callback-trampoline :test #'sap=))
(declare (ignore type args))
(let ((reader (reader-function 'pointer))
(from-alien (from-alien-function 'callback)))
- #'(lambda (location &optional (offset 0))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
(let ((pointer (funcall reader location offset)))
(unless (null-pointer-p pointer)
(funcall from-alien pointer))))))
(defmethod unbound-value ((type (eql 'callback)) &rest args)
(declare (ignore type args))
(values t nil))
+)
\ No newline at end of file