:EXTERN
No alien is allocated, but VAR is established as a local name for
the external alien given by EXTERNAL-NAME."
+ (/show "entering WITH-ALIEN" bindings)
(with-auxiliary-alien-types env
(dolist (binding (reverse bindings))
+ (/show binding)
(destructuring-bind
(symbol type &optional (opt1 nil opt1p) (opt2 nil opt2p))
binding
+ (/show symbol type opt1 opt2)
(let ((alien-type (parse-alien-type type env)))
+ (/show alien-type)
(multiple-value-bind (allocation initial-value)
(if opt2p
(values opt1 opt2)
(values opt1 nil))
(t
(values :local opt1))))
+ (/show allocation initial-value)
(setf body
(ecase allocation
#+nil
`((setq ,symbol ,initial-value)))
,@body)))))
(:extern
+ (/show ":EXTERN case")
(let ((info (make-heap-alien-info
:type alien-type
:sap-form `(foreign-symbol-address
((,symbol (%heap-alien ',info)))
,@body))))
(:local
+ (/show ":LOCAL case")
(let ((var (gensym))
(initval (if initial-value (gensym)))
(info (make-local-alien-info :type alien-type)))
+ (/show var initval info)
`((let ((,var (make-local-alien ',info))
,@(when initial-value
`((,initval ,initial-value))))
`((setq ,symbol ,initval)))
,@body)
(dispose-local-alien ',info ,var))))))))))))
+ (/show "revised" body)
(verify-local-auxiliaries-okay)
+ (/show "back from VERIFY-LOCAL-AUXILIARIES-OK, returning")
`(symbol-macrolet ((&auxiliary-type-definitions&
,(append *new-auxiliary-types*
(auxiliary-type-definitions env))))
(values nil
nil
(list value)
- (if sb!c:*converting-for-interpreter*
- `(%set-local-alien ',info ,alien ,value)
- `(if (%local-alien-forced-to-memory-p ',info)
- (%set-local-alien ',info ,alien ,value)
- (setf ,alien
- (deport ,value ',(local-alien-info-type info)))))
+ `(if (%local-alien-forced-to-memory-p ',info)
+ (%set-local-alien ',info ,alien ,value)
+ (setf ,alien
+ (deport ,value ',(local-alien-info-type info))))
whole)))
(defun %local-alien-forced-to-memory-p (info)
(t
(error "~S is not an alien function." alien)))))
-(defmacro def-alien-routine (name result-type &rest args &environment env)
+(defmacro def-alien-routine (name result-type &rest args &environment lexenv)
#!+sb-doc
- "Def-C-Routine Name Result-Type
- {(Arg-Name Arg-Type [Style])}*
+ "DEF-ALIEN-ROUTINE Name Result-Type {(Arg-Name Arg-Type [Style])}*
- Define a foreign interface function for the routine with the specified Name,
- which may be either a string, symbol or list of the form (string symbol).
- Return-Type is the Alien type for the function return value. VOID may be
- used to specify a function with no result.
+ Define a foreign interface function for the routine with the specified NAME.
+ Also automatically DECLAIM the FTYPE of the defined function.
- The remaining forms specifiy individual arguments that are passed to the
- routine. Arg-Name is a symbol that names the argument, primarily for
- documentation. Arg-Type is the C-Type of the argument. Style specifies the
- say that the argument is passed.
+ NAME may be either a string, a symbol, or a list of the form (string symbol).
+
+ RETURN-TYPE is the alien type for the function return value. VOID may be
+ used to specify a function with no result.
+
+ The remaining forms specify individual arguments that are passed to the
+ routine. ARG-NAME is a symbol that names the argument, primarily for
+ documentation. ARG-TYPE is the C type of the argument. STYLE specifies the
+ way that the argument is passed.
:IN
- An :In argument is simply passed by value. The value to be passed is
+ An :IN argument is simply passed by value. The value to be passed is
obtained from argument(s) to the interface function. No values are
returned for :In arguments. This is the default mode.
to arrays, records or functions.
:COPY
- Similar to :IN, except that the argument values are stored in on
- the stack, and a pointer to the object is passed instead of
- the values themselves.
+ This is similar to :IN, except that the argument values are stored
+ on the stack, and a pointer to the object is passed instead of
+ the value itself.
:IN-OUT
- A combination of :OUT and :COPY. A pointer to the argument is passed,
- with the object being initialized from the supplied argument and
- the return value being determined by accessing the object on return."
+ This is a combination of :OUT and :COPY. A pointer to the argument is
+ passed, with the object being initialized from the supplied argument
+ and the return value being determined by accessing the object on
+ return."
(multiple-value-bind (lisp-name alien-name)
(pick-lisp-and-alien-names name)
(collect ((docs) (lisp-args) (arg-types) (alien-vars)
(unless (eq style :out)
(lisp-args name))
(when (and (member style '(:out :in-out))
- (typep (parse-alien-type type env)
+ (typep (parse-alien-type type lexenv)
'alien-pointer-type))
(error "can't use :OUT or :IN-OUT on pointer-like type:~% ~S"
type))
(alien-args `(addr ,name))))
(when (or (eq style :out) (eq style :in-out))
(results name)))))
- `(defun ,lisp-name ,(lisp-args)
- ,@(docs)
- (with-alien
- ((,lisp-name (function ,result-type ,@(arg-types))
- :extern ,alien-name)
- ,@(alien-vars))
- ,(if (alien-values-type-p result-type)
- (let ((temps (make-gensym-list
- (length
- (alien-values-type-values result-type)))))
- `(multiple-value-bind ,temps
- (alien-funcall ,lisp-name ,@(alien-args))
- (values ,@temps ,@(results))))
- `(values (alien-funcall ,lisp-name ,@(alien-args))
- ,@(results))))))))
+ `(progn
+
+ ;; The theory behind this automatic DECLAIM is that (1) if
+ ;; you're calling C, static typing is what you're doing
+ ;; anyway, and (2) such a declamation can be (especially for
+ ;; alien values) both messy to do by hand and very important
+ ;; for performance of later code which uses the return value.
+ (declaim (ftype (function (mapcar (constantly t) ',args)
+ (alien ,result-type))
+ ,lisp-name))
+
+ (defun ,lisp-name ,(lisp-args)
+ ,@(docs)
+ (with-alien
+ ((,lisp-name (function ,result-type ,@(arg-types))
+ :extern ,alien-name)
+ ,@(alien-vars))
+ ,(if (alien-values-type-p result-type)
+ (let ((temps (make-gensym-list
+ (length
+ (alien-values-type-values result-type)))))
+ `(multiple-value-bind ,temps
+ (alien-funcall ,lisp-name ,@(alien-args))
+ (values ,@temps ,@(results))))
+ `(values (alien-funcall ,lisp-name ,@(alien-args))
+ ,@(results)))))))))
\f
(defun alien-typep (object type)
#!+sb-doc