;; License along with this library; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-;; $Id: gforeign.lisp,v 1.6 2001/04/29 20:05:22 espen Exp $
+;; $Id: gforeign.lisp,v 1.12 2001/10/21 21:33:57 espen Exp $
(in-package "GLIB")
(defun find-applicable-type-method (type-spec fname &optional (error t))
(flet ((find-superclass-method (class)
- (when class
+ (when (and class (class-finalized-p class))
+; (unless (class-finalized-p class)
+; (finalize-inheritance class))
(dolist (super (cdr (pcl::class-precedence-list class)))
(return-if (find-type-method super fname)))))
(find-expanded-type-method (type-spec)
(defmacro defbinding (name lambda-list return-type-spec &rest docs/args)
- (multiple-value-bind (c-name lisp-name)
+ (multiple-value-bind (lisp-name c-name)
(if (atom name)
- (values (default-alien-fname name) name)
- (values-list name))
+ (values name (default-alien-fname name))
+ (values-list name))
+
(let ((supplied-lambda-list lambda-list)
(docs nil)
(args nil))
c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
return-type-spec (reverse docs) (reverse args)))))
-;; For backward compatibility
-(defmacro define-foreign (&rest args)
- `(defbinding ,@args))
-
-
#+cmu
(defun %defbinding (foreign-name lisp-name lambda-list
return-type-spec docs args)
(dolist (arg args)
(destructuring-bind (var expr type-spec style) arg
(let ((declaration (translate-type-spec type-spec))
- (deallocation (cleanup-alien type-spec expr t)))
+ (deallocation (cleanup-alien type-spec var t)))
(cond
((member style '(:out :in-out))
(alien-types `(* ,declaration))
,@(alien-deallocators)
(values ,@(alien-values)))))))))
-
+(defun mkbinding (name return-type &rest arg-types)
+ (declare (optimize (ext:inhibit-warnings 3)))
+ (let* ((ftype
+ `(function
+ ,@(mapcar #'translate-type-spec (cons return-type arg-types))))
+ (alien
+ (alien::%heap-alien
+ (alien::make-heap-alien-info
+ :type (alien::parse-alien-type ftype)
+ :sap-form (system:foreign-symbol-address name))))
+ (translate-arguments
+ (mapcar #'intern-return-value-translator arg-types))
+ (translate-return-value (intern-return-value-translator return-type))
+ (cleanup-arguments (mapcar #'intern-cleanup-function arg-types)))
+
+ #'(lambda (&rest args)
+ (map-into args #'funcall translate-arguments args)
+ (prog1
+ (funcall
+ translate-return-value (apply #'alien:alien-funcall alien args))
+ (mapc #'funcall cleanup-arguments args)))))
+
+
+(defun type-translateable-p (type-spec)
+ (find-applicable-type-method type-spec 'translate-type-spec nil))
+
+(defun every-type-translateable-p (type-specs)
+ (every #'type-translateable-p type-specs))
+
+(defun mkbinding-late (name return-type &rest arg-types)
+ (if (every-type-translateable-p (cons return-type arg-types))
+ (apply #'mkbinding name return-type arg-types)
+ (let ((binding nil))
+ #'(lambda (&rest args)
+ (cond
+ (binding (apply binding args))
+ ((every-type-translateable-p (cons return-type arg-types))
+ (setq binding (apply #'mkbinding name return-type arg-types))
+ (apply binding args))
+ (t
+ (dolist (type-spec (cons return-type arg-types))
+ (unless (type-translateable-p type-spec)
+ (error "Can't translate type ~A" type-spec)))))))))
+
+
;;;; Definitons and translations of fundamental types
(deftype boolean (&optional (size '*))
(declare (ignore size))
`(member t nil))
-(deftype static (type) type)
(deftype invalid () nil)
(defun atomic-type-p (type-spec)
))))
(deftype-method cleanup-alien string (type-spec c-string &optional weak-ref)
- (declare (ignore type-spec))
(when weak-ref
(unreference-alien type-spec c-string)))
(deftype-method unreference-alien string (type-spec c-string)
+ (declare (ignore type-spec))
`(let ((c-string ,c-string))
(unless (null-pointer-p c-string)
(deallocate-memory c-string))))
(deftype-method translate-type-spec nil (type-spec)
(declare (ignore type-spec))
'void)
+
+(deftype-method translate-from-alien nil (type-spec expr &optional weak-ref)
+ (declare (ignore type-spec weak-ref))
+ `(progn
+ ,expr
+ (values)))