0.9.8.34:
[sbcl.git] / src / code / target-alieneval.lisp
index c670384..ff7e49c 100644 (file)
       (t
        (error "~S is not an alien function." alien)))))
 
+(defun alien-funcall-stdcall (alien &rest args)
+  #!+sb-doc
+  "Call the foreign function ALIEN with the specified arguments. ALIEN's
+   type specifies the argument and result types."
+  (declare (type alien-value alien))
+  (let ((type (alien-value-type alien)))
+    (typecase type
+      (alien-pointer-type
+       (apply #'alien-funcall-stdcall (deref alien) args))
+      (alien-fun-type
+       (unless (= (length (alien-fun-type-arg-types type))
+                  (length args))
+         (error "wrong number of arguments for ~S~%expected ~W, got ~W"
+                type
+                (length (alien-fun-type-arg-types type))
+                (length args)))
+       (let ((stub (alien-fun-type-stub type)))
+         (unless stub
+           (setf stub
+                 (let ((fun (gensym))
+                       (parms (make-gensym-list (length args))))
+                   (compile nil
+                            `(lambda (,fun ,@parms)
+                               (declare (optimize (sb!c::insert-step-conditions 0)))
+                               (declare (type (alien ,type) ,fun))
+                               (alien-funcall-stdcall ,fun ,@parms)))))
+           (setf (alien-fun-type-stub type) stub))
+         (apply stub alien args)))
+      (t
+       (error "~S is not an alien function." alien)))))
+
 (defmacro define-alien-routine (name result-type
                                      &rest args
                                      &environment lexenv)
@@ -792,18 +823,19 @@ ENTER-ALIEN-CALLBACK pulls the corresponsing trampoline out and calls it.")
          (argument-names arguments)
          (argument-specs (cddr specifier)))
     `(lambda (args-pointer result-pointer function)
+       ;; FIXME: the saps are not gc safe
        (let ((args-sap (int-sap
                         (sb!kernel:get-lisp-obj-address args-pointer)))
              (res-sap (int-sap
                        (sb!kernel:get-lisp-obj-address result-pointer))))
          (with-alien
              ,(loop
+                 with offset = 0
                  for spec in argument-specs
-                 for offset = 0 ; FIXME: Should this not be AND OFFSET ...?
-                 then (+ offset (alien-callback-argument-bytes spec env))
                  collect `(,(pop argument-names) ,spec
                             :local ,(alien-callback-accessor-form
-                                     spec 'args-sap offset)))
+                                     spec 'args-sap offset))
+                 do (incf offset (alien-callback-argument-bytes spec env)))
            ,(flet ((store (spec)
                           (if spec
                               `(setf (deref (sap-alien res-sap (* ,spec)))
@@ -837,7 +869,8 @@ ENTER-ALIEN-CALLBACK pulls the corresponsing trampoline out and calls it.")
   (destructuring-bind (function result-type &rest argument-types)
       specifier
     (aver (eq 'function function))
-    (values (parse-alien-type result-type env)
+    (values (let ((*values-type-okay* t))
+              (parse-alien-type result-type env))
             (mapcar (lambda (spec)
                       (parse-alien-type spec env))
                     argument-types))))
@@ -862,6 +895,11 @@ ENTER-ALIEN-CALLBACK pulls the corresponsing trampoline out and calls it.")
            return
            arguments))
 
+;;; To ensure that callback wrapper functions continue working even
+;;; if #'ENTER-ALIEN-CALLBACK moves in memory, access to it is indirected
+;;; through the *ENTER-ALIEN-CALLBACK* static symbol. -- JES, 2006-01-01
+(defvar *enter-alien-callback* #'enter-alien-callback)
+
 ;;;; interface (not public, yet) for alien callbacks
 
 (defmacro alien-callback (specifier function &environment env)