+(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-argument-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)))))))))
+
+