1 ;; Common Lisp bindings for GTK+ v2.x
2 ;; Copyright 1999-2005 Espen S. Johnsen <espen@users.sf.net>
4 ;; Permission is hereby granted, free of charge, to any person obtaining
5 ;; a copy of this software and associated documentation files (the
6 ;; "Software"), to deal in the Software without restriction, including
7 ;; without limitation the rights to use, copy, modify, merge, publish,
8 ;; distribute, sublicense, and/or sell copies of the Software, and to
9 ;; permit persons to whom the Software is furnished to do so, subject to
10 ;; the following conditions:
12 ;; The above copyright notice and this permission notice shall be
13 ;; included in all copies or substantial portions of the Software.
15 ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 ;; $Id: ffi.lisp,v 1.24 2006/02/19 19:17:45 espen Exp $
28 ;;;; Foreign function call interface
30 (defvar *package-prefix* nil)
32 (defun set-package-prefix (prefix &optional (package *package*))
33 (let ((package (find-package package)))
34 (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*)
35 (push (cons package prefix) *package-prefix*))
38 (defun package-prefix (&optional (package *package*))
39 (let ((package (find-package package)))
41 (cdr (assoc package *package-prefix*))
42 (substitute #\_ #\- (string-downcase (package-name package))))))
44 (defun find-prefix-package (prefix)
46 (car (rassoc (string-downcase prefix) *package-prefix* :test #'string=))
47 (find-package (string-upcase prefix))))
49 (defmacro use-prefix (prefix &optional (package *package*))
50 `(eval-when (:compile-toplevel :load-toplevel :execute)
51 (set-package-prefix ,prefix ,package)))
54 (defun default-alien-fname (lisp-name)
55 (let* ((name (substitute #\_ #\- (string-downcase lisp-name)))
59 (char= (char name 0) #\%)
60 (string= "_p" name :start2 (- (length name) 2)))
61 (subseq name 1 (- (length name) 2)))
62 ((char= (char name 0) #\%)
64 ((string= "_p" name :start2 (- (length name) 2))
65 (subseq name 0 (- (length name) 2)))
67 (prefix (package-prefix *package*)))
68 (if (or (not prefix) (string= prefix ""))
70 (format nil "~A_~A" prefix stripped-name))))
72 (defun default-alien-type-name (type-name)
73 (let ((prefix (package-prefix *package*)))
79 (cons prefix (split-string (symbol-name type-name) #\-))))))
81 (defun default-type-name (alien-name)
85 (split-string-if alien-name #'upper-case-p))))
88 (rest parts) #\-) (find-prefix-package (first parts)))))
91 (defmacro defbinding (name lambda-list return-type &rest docs/args)
92 (multiple-value-bind (lisp-name c-name)
94 (values name (default-alien-fname name))
97 (let ((supplied-lambda-list lambda-list)
100 (dolist (doc/arg docs/args)
101 (if (stringp doc/arg)
104 (destructuring-bind (expr type &optional (style :in)) doc/arg
105 (unless (member style '(:in :out :in-out :return))
106 (error "Bogus argument style ~S in ~S." style doc/arg))
108 (not supplied-lambda-list)
109 (namep expr) (member style '(:in :in-out :return)))
110 (push expr lambda-list))
112 ((and (namep expr) (eq style :out)) expr)
113 ((namep expr) (make-symbol (string expr)))
115 expr (mklist type) style) args)))))
118 c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
119 return-type (reverse docs) (reverse args)))))
122 (defun %defbinding (foreign-name lisp-name lambda-list return-type docs args)
123 (collect ((alien-types) (alien-bindings) (alien-parameters)
124 (return-values) (cleanup-forms))
126 (destructuring-bind (var expr type style) arg
127 (let ((declaration (alien-type type))
128 (cleanup (cleanup-form var type)))
131 ((member style '(:out :in-out))
132 (alien-types `(* ,declaration))
133 (alien-parameters `(addr ,var))
137 ((eq style :in-out) (list (to-alien-form expr type)))
138 ((eq declaration 'system-area-pointer)
139 (list '(make-pointer 0))))))
140 (return-values (from-alien-form var type)))
142 (alien-types declaration)
144 `(,var ,declaration ,(to-alien-form expr type)))
145 (alien-parameters var)
146 (return-values (from-alien-form var type)))
148 (alien-types declaration)
150 `(,var ,declaration ,(to-alien-form expr type)))
151 (alien-parameters var)
152 (cleanup-forms cleanup))
154 (alien-types declaration)
155 (alien-parameters (to-alien-form expr type)))))))
157 (let* ((alien-name (make-symbol (string lisp-name)))
158 (alien-funcall `(alien-funcall ,alien-name ,@(alien-parameters))))
159 `(defun ,lisp-name ,lambda-list
161 #+cmu(declare (optimize (inhibit-warnings 3)))
162 #+sbcl(declare (muffle-conditions compiler-note))
163 (with-alien ((,alien-name
165 ,(alien-type return-type)
167 :extern ,foreign-name)
172 ,(from-alien-form alien-funcall return-type)
179 (values ,@(return-values)))))))))
182 ;;; Creates bindings at runtime
183 (defun mkbinding (name return-type &rest arg-types)
184 #+cmu(declare (optimize (inhibit-warnings 3)))
185 #+sbcl(declare (muffle-conditions compiler-note))
187 `(function ,@(mapcar #'alien-type (cons return-type arg-types))))
190 (make-heap-alien-info
191 :type (parse-alien-type ftype #+sbcl nil)
192 :sap-form (let ((address (foreign-symbol-address name)))
194 (integer (int-sap address))
195 (system-area-pointer address))))))
196 (translate-arguments (mapcar #'to-alien-function arg-types))
197 (translate-return-value (from-alien-function return-type))
198 (cleanup-arguments (mapcar #'cleanup-function arg-types)))
200 #'(lambda (&rest args)
201 (map-into args #'funcall translate-arguments args)
203 (funcall translate-return-value
204 (apply #'alien-funcall alien args))
205 (mapc #'funcall cleanup-arguments args)))))
211 (defmacro define-callback (name return-type args &body body)
212 (let ((define-callback
213 #+cmu'alien:def-callback
214 #+(and sbcl alien-callbacks)'sb-alien::define-alien-callback
215 #+(and sbcl (not alien-callbacks))'sb-alien:define-alien-function))
216 (multiple-value-bind (doc declaration body)
218 ((and (stringp (first body)) (eq (cadr body) 'declare))
219 (values (first body) (second body) (cddr body)))
220 ((stringp (first body))
221 (values (first body) nil (rest body)))
222 ((eq (caar body) 'declare)
223 (values nil (first body) (rest body)))
224 (t (values nil nil body)))
225 `(,define-callback ,name
226 #+(and sbcl alien-callbacks),(alien-type return-type)
227 (#+(or cmu (and sbcl (not alien-callbacks))),(alien-type return-type)
228 ,@(mapcar #'(lambda (arg)
229 (destructuring-bind (name type) arg
230 `(,name ,(alien-type type))))
232 ,@(when doc (list doc))
235 for (name type) in args
236 as from-alien-form = (callback-from-alien-form name type)
237 collect `(,name ,from-alien-form)))
238 ,@(when declaration (list declaration))
242 for (name type) in args
243 do (callback-cleanup-form name type))))
247 (defun callback-address (callback)
248 #+cmu(alien::callback-trampoline callback)
249 #+(and sbcl (not alien-callbacks))(sb-alien:alien-function-sap callback)
250 #+(and sbcl alien-callbacks)(sb-alien:alien-sap callback))
254 #-alien-callbacks'sb-alien:alien-function
255 #+alien-callbacks'sb-alien:alien)
258 ;;; These are for backward compatibility
260 (defmacro defcallback (name (return-type &rest args) &body body)
261 `(define-callback ,name ,return-type ,args ,@body))
264 (defun callback (callback)
265 (callback-address callback))
269 ;;;; Definitons and translations of fundamental types
271 (defmacro def-type-method (name args &optional documentation)
273 (defgeneric ,name (,@args type &rest args)
274 ,@(when documentation `((:documentation ,documentation))))
275 (defmethod ,name (,@args (type symbol) &rest args)
276 (let ((class (find-class type nil)))
278 (apply #',name ,@args class args)
279 (multiple-value-bind (super-type expanded-p)
280 (type-expand-1 (cons type args))
282 (,name ,@args super-type)
283 (call-next-method))))))
284 (defmethod ,name (,@args (type cons) &rest args)
285 (declare (ignore args))
286 (apply #',name ,@args (first type) (rest type)))))
289 (def-type-method alien-type ())
290 (def-type-method size-of ())
291 (def-type-method to-alien-form (form))
292 (def-type-method from-alien-form (form))
293 (def-type-method cleanup-form (form)
294 "Creates a form to clean up after the alien call has finished.")
295 (def-type-method callback-from-alien-form (form))
296 (def-type-method callback-cleanup-form (form))
298 (def-type-method to-alien-function ())
299 (def-type-method from-alien-function ())
300 (def-type-method cleanup-function ())
302 (def-type-method copy-to-alien-form (form))
303 (def-type-method copy-to-alien-function ())
304 (def-type-method copy-from-alien-form (form))
305 (def-type-method copy-from-alien-function ())
307 (def-type-method writer-function ())
308 (def-type-method reader-function ())
309 (def-type-method destroy-function ())
311 (def-type-method unbound-value ()
312 "First return value is true if the type has an unbound value, second return value is the actual unbound value")
315 ;; Sizes of fundamental C types in bytes (8 bits)
316 (defconstant +size-of-short+ 2)
317 (defconstant +size-of-int+ 4)
318 (defconstant +size-of-long+ 4)
319 (defconstant +size-of-pointer+ 4)
320 (defconstant +size-of-float+ 4)
321 (defconstant +size-of-double+ 8)
323 ;; Sizes of fundamental C types in bits
324 (defconstant +bits-of-byte+ 8)
325 (defconstant +bits-of-short+ 16)
326 (defconstant +bits-of-int+ 32)
327 (defconstant +bits-of-long+ 32)
330 (deftype int () '(signed-byte #.+bits-of-int+))
331 (deftype unsigned-int () '(unsigned-byte #.+bits-of-int+))
332 (deftype long () '(signed-byte #.+bits-of-long+))
333 (deftype unsigned-long () '(unsigned-byte #.+bits-of-long+))
334 (deftype short () '(signed-byte #.+bits-of-short+))
335 (deftype unsigned-short () '(unsigned-byte #.+bits-of-short+))
336 (deftype signed (&optional (size '*)) `(signed-byte ,size))
337 (deftype unsigned (&optional (size '*)) `(unsigned-byte ,size))
338 (deftype char () 'base-char)
339 (deftype pointer () 'system-area-pointer)
340 (deftype boolean (&optional (size '*)) (declare (ignore size)) `(member t nil))
341 ;(deftype invalid () nil)
344 (defmethod to-alien-form (form (type t) &rest args)
345 (declare (ignore type args))
348 (defmethod to-alien-function ((type t) &rest args)
349 (declare (ignore type args))
352 (defmethod from-alien-form (form (type t) &rest args)
353 (declare (ignore type args))
356 (defmethod from-alien-function ((type t) &rest args)
357 (declare (ignore type args))
360 (defmethod cleanup-form (form (type t) &rest args)
361 (declare (ignore form type args))
364 (defmethod cleanup-function ((type t) &rest args)
365 (declare (ignore type args))
368 (defmethod callback-from-alien-form (form (type t) &rest args)
369 (apply #'copy-from-alien-form form type args))
371 (defmethod callback-cleanup-form (form (type t) &rest args)
372 (declare (ignore form type args))
375 (defmethod destroy-function ((type t) &rest args)
376 (declare (ignore type args))
377 #'(lambda (location &optional offset)
378 (declare (ignore location offset))))
380 (defmethod copy-to-alien-form (form (type t) &rest args)
381 (apply #'to-alien-form form type args))
383 (defmethod copy-to-alien-function ((type t) &rest args)
384 (apply #'to-alien-function type args))
386 (defmethod copy-from-alien-form (form (type t) &rest args)
387 (apply #'from-alien-form form type args))
389 (defmethod copy-from-alien-function ((type t) &rest args)
390 (apply #'from-alien-function type args))
392 (defmethod alien-type ((type (eql 'signed-byte)) &rest args)
393 (declare (ignore type))
394 (destructuring-bind (&optional (size '*)) args
396 (#.+bits-of-byte+ #+cmu'(alien:signed 8) #+sbcl'(sb-alien:signed 8))
397 (#.+bits-of-short+ #+cmu 'c-call:short #+sbcl 'sb-alien:short)
398 ((* #.+bits-of-int+) #+cmu 'c-call:int #+sbcl 'sb-alien:int)
399 (#.+bits-of-long+ #+cmu 'c-call:long #+sbcl 'sb-alien:long))))
401 (defmethod size-of ((type (eql 'signed-byte)) &rest args)
402 (declare (ignore type))
403 (destructuring-bind (&optional (size '*)) args
406 (#.+bits-of-short+ +size-of-short+)
407 ((* #.+bits-of-int+) +size-of-int+)
408 (#.+bits-of-long+ +size-of-long+))))
410 (defmethod unbound-value ((type t) &rest args)
411 (declare (ignore type args))
414 (defmethod writer-function ((type (eql 'signed-byte)) &rest args)
415 (declare (ignore type))
416 (destructuring-bind (&optional (size '*)) args
417 (let ((size (if (eq size '*) +bits-of-int+ size)))
419 (8 #'(lambda (value location &optional (offset 0))
420 (setf (signed-sap-ref-8 location offset) value)))
421 (16 #'(lambda (value location &optional (offset 0))
422 (setf (signed-sap-ref-16 location offset) value)))
423 (32 #'(lambda (value location &optional (offset 0))
424 (setf (signed-sap-ref-32 location offset) value)))
425 (64 #'(lambda (value location &optional (offset 0))
426 (setf (signed-sap-ref-64 location offset) value)))))))
428 (defmethod reader-function ((type (eql 'signed-byte)) &rest args)
429 (declare (ignore type))
430 (destructuring-bind (&optional (size '*)) args
431 (let ((size (if (eq size '*) +bits-of-int+ size)))
433 (8 #'(lambda (sap &optional (offset 0) weak-p)
434 (declare (ignore weak-p))
435 (signed-sap-ref-8 sap offset)))
436 (16 #'(lambda (sap &optional (offset 0) weak-p)
437 (declare (ignore weak-p))
438 (signed-sap-ref-16 sap offset)))
439 (32 #'(lambda (sap &optional (offset 0) weak-p)
440 (declare (ignore weak-p))
441 (signed-sap-ref-32 sap offset)))
442 (64 #'(lambda (sap &optional (offset 0) weak-p)
443 (declare (ignore weak-p))
444 (signed-sap-ref-64 sap offset)))))))
446 (defmethod alien-type ((type (eql 'unsigned-byte)) &rest args)
447 (destructuring-bind (&optional (size '*)) args
449 (#.+bits-of-byte+ #+cmu'(alien:unsigned 8) #+sbcl'(sb-alien:unsigned 8))
450 (#.+bits-of-short+ #+cmu 'c-call:unsigned-short
451 #+sbcl 'sb-alien:unsigned-short)
452 ((* #.+bits-of-int+) #+cmu 'c-call:unsigned-int
453 #+sbcl 'sb-alien:unsigned-int)
454 (#.+bits-of-long+ #+cmu 'c-call:unsigned-long
455 #+sbcl 'sb-alien:unsigned-long))))
457 (defmethod size-of ((type (eql 'unsigned-byte)) &rest args)
458 (apply #'size-of 'signed args))
460 (defmethod writer-function ((type (eql 'unsigned-byte)) &rest args)
461 (declare (ignore type))
462 (destructuring-bind (&optional (size '*)) args
463 (let ((size (if (eq size '*) +bits-of-int+ size)))
465 (8 #'(lambda (value location &optional (offset 0))
466 (setf (sap-ref-8 location offset) value)))
467 (16 #'(lambda (value location &optional (offset 0))
468 (setf (sap-ref-16 location offset) value)))
469 (32 #'(lambda (value location &optional (offset 0))
470 (setf (sap-ref-32 location offset) value)))
471 (64 #'(lambda (value location &optional (offset 0))
472 (setf (sap-ref-64 location offset) value)))))))
474 (defmethod reader-function ((type (eql 'unsigned-byte)) &rest args)
475 (declare (ignore type))
476 (destructuring-bind (&optional (size '*)) args
477 (let ((size (if (eq size '*) +bits-of-int+ size)))
479 (8 #'(lambda (sap &optional (offset 0) weak-p)
480 (declare (ignore weak-p))
481 (sap-ref-8 sap offset)))
482 (16 #'(lambda (sap &optional (offset 0) weak-p)
483 (declare (ignore weak-p))
484 (sap-ref-16 sap offset)))
485 (32 #'(lambda (sap &optional (offset 0) weak-p)
486 (declare (ignore weak-p))
487 (sap-ref-32 sap offset)))
488 (64 #'(lambda (sap &optional (offset 0) weak-p)
489 (declare (ignore weak-p))
490 (sap-ref-64 sap offset)))))))
493 (defmethod alien-type ((type (eql 'integer)) &rest args)
494 (declare (ignore type args))
495 (alien-type 'signed-byte))
497 (defmethod size-of ((type (eql 'integer)) &rest args)
498 (declare (ignore type args))
499 (size-of 'signed-byte))
501 (defmethod writer-function ((type (eql 'integer)) &rest args)
502 (declare (ignore type args))
503 (writer-function 'signed-byte))
505 (defmethod reader-function ((type (eql 'integer)) &rest args)
506 (declare (ignore type args))
507 (reader-function 'signed-byte))
510 (defmethod alien-type ((type (eql 'fixnum)) &rest args)
511 (declare (ignore type args))
512 (alien-type 'signed-byte))
514 (defmethod size-of ((type (eql 'fixnum)) &rest args)
515 (declare (ignore type args))
516 (size-of 'signed-byte))
519 (defmethod alien-type ((type (eql 'single-float)) &rest args)
520 (declare (ignore type args))
521 #+cmu 'alien:single-float #+sbcl 'sb-alien:single-float)
523 (defmethod size-of ((type (eql 'single-float)) &rest args)
524 (declare (ignore type args))
527 (defmethod to-alien-form (form (type (eql 'single-float)) &rest args)
528 (declare (ignore type args))
529 `(coerce ,form 'single-float))
531 (defmethod to-alien-function ((type (eql 'single-float)) &rest args)
532 (declare (ignore type args))
534 (coerce number 'single-float)))
536 (defmethod writer-function ((type (eql 'single-float)) &rest args)
537 (declare (ignore type args))
538 #'(lambda (value location &optional (offset 0))
539 (setf (sap-ref-single location offset) (coerce value 'single-float))))
541 (defmethod reader-function ((type (eql 'single-float)) &rest args)
542 (declare (ignore type args))
543 #'(lambda (sap &optional (offset 0) weak-p)
544 (declare (ignore weak-p))
545 (sap-ref-single sap offset)))
548 (defmethod alien-type ((type (eql 'double-float)) &rest args)
549 (declare (ignore type args))
550 #+cmu 'alien:double-float #+sbcl 'sb-alien:double-float)
552 (defmethod size-of ((type (eql 'double-float)) &rest args)
553 (declare (ignore type args))
556 (defmethod to-alien-form (form (type (eql 'double-float)) &rest args)
557 (declare (ignore type args))
558 `(coerce ,form 'double-float))
560 (defmethod to-alien-function ((type (eql 'double-float)) &rest args)
561 (declare (ignore type args))
563 (coerce number 'double-float)))
565 (defmethod writer-function ((type (eql 'double-float)) &rest args)
566 (declare (ignore type args))
567 #'(lambda (value location &optional (offset 0))
568 (setf (sap-ref-double location offset) (coerce value 'double-float))))
570 (defmethod reader-function ((type (eql 'double-float)) &rest args)
571 (declare (ignore type args))
572 #'(lambda (sap &optional (offset 0) weak-p)
573 (declare (ignore weak-p))
574 (sap-ref-double sap offset)))
577 (defmethod alien-type ((type (eql 'base-char)) &rest args)
578 (declare (ignore type args))
579 #+cmu 'c-call:char #+sbcl 'sb-alien:char)
581 (defmethod size-of ((type (eql 'base-char)) &rest args)
582 (declare (ignore type args))
585 (defmethod writer-function ((type (eql 'base-char)) &rest args)
586 (declare (ignore type args))
587 #'(lambda (char location &optional (offset 0))
588 (setf (sap-ref-8 location offset) (char-code char))))
590 (defmethod reader-function ((type (eql 'base-char)) &rest args)
591 (declare (ignore type args))
592 #'(lambda (location &optional (offset 0) weak-p)
593 (declare (ignore weak-p))
594 (code-char (sap-ref-8 location offset))))
597 (defmethod alien-type ((type (eql 'string)) &rest args)
598 (declare (ignore type args))
599 (alien-type 'pointer))
601 (defmethod size-of ((type (eql 'string)) &rest args)
602 (declare (ignore type args))
605 (defmethod to-alien-form (string (type (eql 'string)) &rest args)
606 (declare (ignore type args))
607 `(let ((string ,string))
608 ;; Always copy strings to prevent seg fault due to GC
611 (vector-sap (coerce string 'simple-base-string))
612 (1+ (length string)))
614 (let ((utf8 (%deport-utf8-string string)))
615 (copy-memory (vector-sap utf8) (length utf8)))))
617 (defmethod to-alien-function ((type (eql 'string)) &rest args)
618 (declare (ignore type args))
622 (vector-sap (coerce string 'simple-base-string))
623 (1+ (length string)))
625 (let ((utf8 (%deport-utf8-string string)))
626 (copy-memory (vector-sap utf8) (length utf8)))))
628 (defmethod from-alien-form (string (type (eql 'string)) &rest args)
629 (declare (ignore type args))
630 `(let ((string ,string))
631 (unless (null-pointer-p string)
633 #+cmu(%naturalize-c-string string)
634 #+sbcl(%naturalize-utf8-string string)
635 (deallocate-memory string)))))
637 (defmethod from-alien-function ((type (eql 'string)) &rest args)
638 (declare (ignore type args))
640 (unless (null-pointer-p string)
642 #+cmu(%naturalize-c-string string)
643 #+sbcl(%naturalize-utf8-string string)
644 (deallocate-memory string)))))
646 (defmethod cleanup-form (string (type (eql 'string)) &rest args)
647 (declare (ignore type args))
648 `(let ((string ,string))
649 (unless (null-pointer-p string)
650 (deallocate-memory string))))
652 (defmethod cleanup-function ((type (eql 'string)) &rest args)
653 (declare (ignore args))
655 (unless (null-pointer-p string)
656 (deallocate-memory string))))
658 (defmethod copy-from-alien-form (string (type (eql 'string)) &rest args)
659 (declare (ignore type args))
660 `(let ((string ,string))
661 (unless (null-pointer-p string)
662 #+cmu(%naturalize-c-string string)
663 #+sbcl(%naturalize-utf8-string string))))
665 (defmethod copy-from-alien-function ((type (eql 'string)) &rest args)
666 (declare (ignore type args))
668 (unless (null-pointer-p string)
669 #+cmu(%naturalize-c-string string)
670 #+sbcl(%naturalize-utf8-string string))))
672 (defmethod writer-function ((type (eql 'string)) &rest args)
673 (declare (ignore type args))
674 #'(lambda (string location &optional (offset 0))
675 (assert (null-pointer-p (sap-ref-sap location offset)))
676 (setf (sap-ref-sap location offset)
679 (vector-sap (coerce string 'simple-base-string))
680 (1+ (length string)))
682 (let ((utf8 (%deport-utf8-string string)))
683 (copy-memory (vector-sap utf8) (length utf8))))))
685 (defmethod reader-function ((type (eql 'string)) &rest args)
686 (declare (ignore type args))
687 #'(lambda (location &optional (offset 0) weak-p)
688 (declare (ignore weak-p))
689 (unless (null-pointer-p (sap-ref-sap location offset))
690 #+cmu(%naturalize-c-string (sap-ref-sap location offset))
691 #+sbcl(%naturalize-utf8-string (sap-ref-sap location offset)))))
693 (defmethod destroy-function ((type (eql 'string)) &rest args)
694 (declare (ignore type args))
695 #'(lambda (location &optional (offset 0))
696 (unless (null-pointer-p (sap-ref-sap location offset))
697 (deallocate-memory (sap-ref-sap location offset))
698 (setf (sap-ref-sap location offset) (make-pointer 0)))))
700 (defmethod unbound-value ((type (eql 'string)) &rest args)
701 (declare (ignore type args))
705 (defmethod alien-type ((type (eql 'pathname)) &rest args)
706 (declare (ignore type args))
707 (alien-type 'string))
709 (defmethod size-of ((type (eql 'pathname)) &rest args)
710 (declare (ignore type args))
713 (defmethod to-alien-form (path (type (eql 'pathname)) &rest args)
714 (declare (ignore type args))
715 (to-alien-form `(namestring (translate-logical-pathname ,path)) 'string))
717 (defmethod to-alien-function ((type (eql 'pathname)) &rest args)
718 (declare (ignore type args))
719 (let ((string-function (to-alien-function 'string)))
721 (funcall string-function (namestring path)))))
723 (defmethod from-alien-form (string (type (eql 'pathname)) &rest args)
724 (declare (ignore type args))
725 `(parse-namestring ,(from-alien-form string 'string)))
727 (defmethod from-alien-function ((type (eql 'pathname)) &rest args)
728 (declare (ignore type args))
729 (let ((string-function (from-alien-function 'string)))
731 (parse-namestring (funcall string-function string)))))
733 (defmethod cleanup-form (string (type (eql 'pathnanme)) &rest args)
734 (declare (ignore type args))
735 (cleanup-form string 'string))
737 (defmethod cleanup-function ((type (eql 'pathnanme)) &rest args)
738 (declare (ignore type args))
739 (cleanup-function 'string))
741 (defmethod writer-function ((type (eql 'pathname)) &rest args)
742 (declare (ignore type args))
743 (let ((string-writer (writer-function 'string)))
744 #'(lambda (path location &optional (offset 0))
745 (funcall string-writer (namestring path) location offset))))
747 (defmethod reader-function ((type (eql 'pathname)) &rest args)
748 (declare (ignore type args))
749 (let ((string-reader (reader-function 'string)))
750 #'(lambda (location &optional (offset 0) weak-p)
751 (declare (ignore weak-p))
752 (let ((string (funcall string-reader location offset)))
754 (parse-namestring string))))))
756 (defmethod destroy-function ((type (eql 'pathname)) &rest args)
757 (declare (ignore type args))
758 (destroy-function 'string))
760 (defmethod unbound-value ((type (eql 'pathname)) &rest args)
761 (declare (ignore type args))
762 (unbound-value 'string))
765 (defmethod alien-type ((type (eql 'boolean)) &rest args)
766 (apply #'alien-type 'signed-byte args))
768 (defmethod size-of ((type (eql 'boolean)) &rest args)
769 (apply #'size-of 'signed-byte args))
771 (defmethod to-alien-form (boolean (type (eql 'boolean)) &rest args)
772 (declare (ignore type args))
775 (defmethod to-alien-function ((type (eql 'boolean)) &rest args)
776 (declare (ignore type args))
780 (defmethod from-alien-form (boolean (type (eql 'boolean)) &rest args)
781 (declare (ignore type args))
782 `(not (zerop ,boolean)))
784 (defmethod from-alien-function ((type (eql 'boolean)) &rest args)
785 (declare (ignore type args))
787 (not (zerop boolean))))
789 (defmethod writer-function ((type (eql 'boolean)) &rest args)
790 (declare (ignore type))
791 (let ((writer (apply #'writer-function 'signed-byte args)))
792 #'(lambda (boolean location &optional (offset 0))
793 (funcall writer (if boolean 1 0) location offset))))
795 (defmethod reader-function ((type (eql 'boolean)) &rest args)
796 (declare (ignore type))
797 (let ((reader (apply #'reader-function 'signed-byte args)))
798 #'(lambda (location &optional (offset 0) weak-p)
799 (declare (ignore weak-p))
800 (not (zerop (funcall reader location offset))))))
803 (defmethod alien-type ((type (eql 'or)) &rest args)
804 (let ((alien-type (alien-type (first args))))
805 (unless (every #'(lambda (type)
806 (eq alien-type (alien-type type)))
808 (error "No common alien type specifier for union type: ~A"
812 (defmethod size-of ((type (eql 'or)) &rest args)
813 (declare (ignore type))
814 (size-of (first args)))
816 (defmethod to-alien-form (form (type (eql 'or)) &rest args)
817 (declare (ignore type))
818 `(let ((value ,form))
822 `(,type ,(to-alien-form 'value type)))
825 (defmethod to-alien-function ((type (eql 'or)) &rest types)
826 (declare (ignore type))
827 (let ((functions (mapcar #'to-alien-function types)))
830 for function in functions
832 when (typep value type)
833 do (return (funcall function value))
834 finally (error "~S is not of type ~A" value `(or ,@types))))))
836 (defmethod alien-type ((type (eql 'system-area-pointer)) &rest args)
837 (declare (ignore type args))
838 'system-area-pointer)
840 (defmethod size-of ((type (eql 'system-area-pointer)) &rest args)
841 (declare (ignore type args))
844 (defmethod writer-function ((type (eql 'system-area-pointer)) &rest args)
845 (declare (ignore type args))
846 #'(lambda (sap location &optional (offset 0))
847 (setf (sap-ref-sap location offset) sap)))
849 (defmethod reader-function ((type (eql 'system-area-pointer)) &rest args)
850 (declare (ignore type args))
851 #'(lambda (location &optional (offset 0) weak-p)
852 (declare (ignore weak-p))
853 (sap-ref-sap location offset)))
856 (defmethod alien-type ((type (eql 'null)) &rest args)
857 (declare (ignore type args))
858 (alien-type 'pointer))
860 (defmethod size-of ((type (eql 'null)) &rest args)
861 (declare (ignore type args))
864 (defmethod to-alien-form (null (type (eql 'null)) &rest args)
865 (declare (ignore null type args))
868 (defmethod to-alien-function ((type (eql 'null)) &rest args)
869 (declare (ignore type args))
871 (declare (ignore null))
875 (defmethod alien-type ((type (eql 'nil)) &rest args)
876 (declare (ignore type args))
879 (defmethod from-alien-function ((type (eql 'nil)) &rest args)
880 (declare (ignore type args))
882 (declare (ignore value))
886 (defmethod alien-type ((type (eql 'copy-of)) &rest args)
887 (declare (ignore type))
888 (alien-type (first args)))
890 (defmethod size-of ((type (eql 'copy-of)) &rest args)
891 (declare (ignore type))
892 (size-of (first args)))
894 (defmethod to-alien-form (form (type (eql 'copy-of)) &rest args)
895 (declare (ignore type))
896 (copy-to-alien-form form (first args)))
898 (defmethod to-alien-function ((type (eql 'copy-of)) &rest args)
899 (declare (ignore type))
900 (copy-to-alien-function (first args)))
902 (defmethod from-alien-form (form (type (eql 'copy-of)) &rest args)
903 (declare (ignore type))
904 (copy-from-alien-form form (first args)))
906 (defmethod from-alien-function ((type (eql 'copy-of)) &rest args)
907 (declare (ignore type))
908 (copy-from-alien-function (first args)))
910 (defmethod reader-function ((type (eql 'copy-of)) &rest args)
911 (declare (ignore type))
912 (reader-function (first args)))
914 (defmethod writer-function ((type (eql 'copy-of)) &rest args)
915 (declare (ignore type))
916 (writer-function (first args)))
919 (defmethod alien-type ((type (eql 'callback)) &rest args)
920 (declare (ignore type args))
921 (alien-type 'pointer))
924 (defmethod size-of ((type (eql 'callback)) &rest args)
925 (declare (ignore type args))
928 (defmethod to-alien-form (callback (type (eql 'callback)) &rest args)
929 (declare (ignore type args))
930 `(callback-address ,callback))
932 (defmethod to-alien-function ((type (eql 'callback)) &rest args)
933 (declare (ignore type args))
938 (defun find-callback (pointer)
939 (find pointer alien::*callbacks* :key #'callback-trampoline :test #'sap=))
941 (defmethod from-alien-form (pointer (type (eql 'callback)) &rest args)
942 (declare (ignore type args))
943 #+cmu `(find-callback ,pointer)
944 #+sbcl `(sb-alien::%find-alien-function ,pointer))
946 (defmethod from-alien-function ((type (eql 'callback)) &rest args)
947 (declare (ignore type args))
948 #+cmu #'find-callback
949 #+sbcl #'sb-alien::%find-alien-function)
951 (defmethod writer-function ((type (eql 'callback)) &rest args)
952 (declare (ignore type args))
953 (let ((writer (writer-function 'pointer))
954 (to-alien (to-alien-function 'callback)))
955 #'(lambda (callback location &optional (offset 0))
956 (funcall writer (funcall to-alien callback) location offset))))
958 (defmethod reader-function ((type (eql 'callback)) &rest args)
959 (declare (ignore type args))
960 (let ((reader (reader-function 'pointer))
961 (from-alien (from-alien-function 'callback)))
962 #'(lambda (location &optional (offset 0) weak-p)
963 (declare (ignore weak-p))
964 (let ((pointer (funcall reader location offset)))
965 (unless (null-pointer-p pointer)
966 (funcall from-alien pointer))))))
968 (defmethod unbound-value ((type (eql 'callback)) &rest args)
969 (declare (ignore type args))