X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Fcode%2Ftarget-alieneval.lisp;h=ff7e49c6149531621414ee2daaf10f9d5d787e17;hb=48ec282d877900caf5ea4ab42e9d87e566ce6b43;hp=c670384d70373423764ff1ea0a280624557a79ff;hpb=077315581ebab63f28bed96c28fd62626fed42ef;p=sbcl.git diff --git a/src/code/target-alieneval.lisp b/src/code/target-alieneval.lisp index c670384..ff7e49c 100644 --- a/src/code/target-alieneval.lisp +++ b/src/code/target-alieneval.lisp @@ -587,6 +587,37 @@ (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)