chiark / gitweb /
Changed metaclass of gobject from ginstance-class to gobject-class
[clg] / glib / ffi.lisp
CommitLineData
310da1d5 1;; Common Lisp bindings for GTK+ v2.0
2;; Copyright (C) 1999-2001 Espen S. Johnsen <esj@stud.cs.uit.no>
3;;
4;; This library is free software; you can redistribute it and/or
5;; modify it under the terms of the GNU Lesser General Public
6;; License as published by the Free Software Foundation; either
7;; version 2 of the License, or (at your option) any later version.
8;;
9;; This library is distributed in the hope that it will be useful,
10;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12;; Lesser General Public License for more details.
13;;
14;; You should have received a copy of the GNU Lesser General Public
15;; License along with this library; if not, write to the Free Software
16;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
8755b1a5 18;; $Id: ffi.lisp,v 1.3 2004-11-07 01:23:38 espen Exp $
310da1d5 19
20(in-package "GLIB")
21
310da1d5 22
23;;;; Foreign function call interface
24
25(defvar *package-prefix* nil)
26
27(defun set-package-prefix (prefix &optional (package *package*))
28 (let ((package (find-package package)))
29 (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*)
30 (push (cons package prefix) *package-prefix*))
31 prefix)
32
33(defun package-prefix (&optional (package *package*))
34 (let ((package (find-package package)))
35 (or
36 (cdr (assoc package *package-prefix*))
37 (substitute #\_ #\- (string-downcase (package-name package))))))
38
39(defun find-prefix-package (prefix)
40 (or
41 (car (rassoc (string-downcase prefix) *package-prefix* :test #'string=))
42 (find-package (string-upcase prefix))))
43
44(defmacro use-prefix (prefix &optional (package *package*))
45 `(eval-when (:compile-toplevel :load-toplevel :execute)
46 (set-package-prefix ,prefix ,package)))
47
48
49(defun default-alien-fname (lisp-name)
50 (let* ((lisp-name-string
51 (if (char= (char (the simple-string (string lisp-name)) 0) #\%)
52 (subseq (the simple-string (string lisp-name)) 1)
53 (string lisp-name)))
54 (prefix (package-prefix *package*))
55 (name (substitute #\_ #\- (string-downcase lisp-name-string))))
56 (if (or (not prefix) (string= prefix ""))
57 name
58 (format nil "~A_~A" prefix name))))
59
60(defun default-alien-type-name (type-name)
61 (let ((prefix (package-prefix *package*)))
62 (apply
63 #'concatenate
64 'string
65 (mapcar
66 #'string-capitalize
67 (cons prefix (split-string (symbol-name type-name) #\-))))))
68
69(defun default-type-name (alien-name)
70 (let ((parts
71 (mapcar
72 #'string-upcase
73 (split-string-if alien-name #'upper-case-p))))
74 (intern
75 (concatenate-strings
76 (rest parts) #\-) (find-prefix-package (first parts)))))
77
78
9adccb27 79(defmacro defbinding (name lambda-list return-type &rest docs/args)
310da1d5 80 (multiple-value-bind (lisp-name c-name)
81 (if (atom name)
82 (values name (default-alien-fname name))
83 (values-list name))
84
85 (let ((supplied-lambda-list lambda-list)
86 (docs nil)
87 (args nil))
88 (dolist (doc/arg docs/args)
89 (if (stringp doc/arg)
90 (push doc/arg docs)
91 (progn
92 (destructuring-bind (expr type &optional (style :in)) doc/arg
93 (unless (member style '(:in :out :in-out))
94 (error "Bogus argument style ~S in ~S." style doc/arg))
95 (when (and
96 (not supplied-lambda-list)
97 (namep expr) (member style '(:in :in-out)))
98 (push expr lambda-list))
99 (push
9adccb27 100 (list (if (namep expr)
101 (make-symbol (string expr))
102 (gensym))
103 expr (mklist type) style) args)))))
310da1d5 104
105 (%defbinding
106 c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
9adccb27 107 return-type (reverse docs) (reverse args)))))
310da1d5 108
109#+cmu
9adccb27 110(defun %defbinding (foreign-name lisp-name lambda-list return-type docs args)
111 (ext:collect ((alien-types) (alien-bindings) (alien-parameters)
112 (alien-values) (cleanup-forms))
310da1d5 113 (dolist (arg args)
9adccb27 114 (destructuring-bind (var expr type style) arg
115 (let ((declaration (alien-type type))
116 (cleanup (cleanup-form var type)))
117
310da1d5 118 (cond
119 ((member style '(:out :in-out))
120 (alien-types `(* ,declaration))
121 (alien-parameters `(addr ,var))
122 (alien-bindings
123 `(,var ,declaration
124 ,@(when (eq style :in-out)
9adccb27 125 (list (to-alien-form expr type)))))
126 (alien-values (from-alien-form var type)))
127 (cleanup
310da1d5 128 (alien-types declaration)
129 (alien-bindings
9adccb27 130 `(,var ,declaration ,(to-alien-form expr type)))
310da1d5 131 (alien-parameters var)
9adccb27 132 (cleanup-forms cleanup))
310da1d5 133 (t
134 (alien-types declaration)
9adccb27 135 (alien-parameters (to-alien-form expr type)))))))
310da1d5 136
137 (let* ((alien-name (make-symbol (string lisp-name)))
138 (alien-funcall `(alien-funcall ,alien-name ,@(alien-parameters))))
139 `(defun ,lisp-name ,lambda-list
140 ,@docs
141 (declare (optimize (ext:inhibit-warnings 3)))
142 (with-alien ((,alien-name
143 (function
9adccb27 144 ,(alien-type return-type)
310da1d5 145 ,@(alien-types))
146 :extern ,foreign-name)
147 ,@(alien-bindings))
9adccb27 148 ,(if return-type
149 `(values
150 (unwind-protect
151 ,(from-alien-form alien-funcall return-type)
152 ,@(cleanup-forms))
153 ,@(alien-values))
310da1d5 154 `(progn
9adccb27 155 (unwind-protect
156 ,alien-funcall
157 ,@(cleanup-forms))
158 (values ,@(alien-values)))))))))
310da1d5 159
160
9adccb27 161;;; Creates bindings at runtime
310da1d5 162(defun mkbinding (name return-type &rest arg-types)
9adccb27 163 (declare (optimize (ext:inhibit-warnings 3)))
164 (let* ((ftype
165 `(function ,@(mapcar #'alien-type (cons return-type arg-types))))
310da1d5 166 (alien
167 (alien::%heap-alien
168 (alien::make-heap-alien-info
169 :type (alien::parse-alien-type ftype)
170 :sap-form (system:foreign-symbol-address name :flavor :code))))
9adccb27 171 (translate-arguments (mapcar #'to-alien-function arg-types))
172 (translate-return-value (from-alien-function return-type))
173 (cleanup-arguments (mapcar #'cleanup-function arg-types)))
174
310da1d5 175 #'(lambda (&rest args)
176 (map-into args #'funcall translate-arguments args)
177 (prog1
9adccb27 178 (funcall translate-return-value
179 (apply #'alien:alien-funcall alien args))
310da1d5 180 (mapc #'funcall cleanup-arguments args)))))
181
8755b1a5 182
183(defmacro defcallback (name (return-type &rest args) &body body)
184 `(def-callback ,name
185 (,(alien-type return-type)
186 ,@(mapcar #'(lambda (arg)
187 (destructuring-bind (name type) arg
188 `(,name ,(alien-type type))))
189 args))
190 ,(to-alien-form
191 `(let (,@(mapcar #'(lambda (arg)
192 (destructuring-bind (name type) arg
193 `(,name ,(from-alien-form name type))))
194 args))
195 ,@body)
196 return-type)))
197
198
310da1d5 199
200;;;; Definitons and translations of fundamental types
201
9adccb27 202(defmacro def-type-method (name args &optional documentation)
203 `(progn
204 (defgeneric ,name (,@args type &rest args)
205 ,@(when documentation `((:documentation ,documentation))))
206 (defmethod ,name (,@args (type symbol) &rest args)
207 (let ((class (find-class type nil)))
208 (if class
209 (apply #',name ,@args class args)
210 (multiple-value-bind (super-type expanded-p)
211 (type-expand-1 (cons type args))
212 (if expanded-p
213 (,name ,@args super-type)
214 (call-next-method))))))
215 (defmethod ,name (,@args (type cons) &rest args)
216 (declare (ignore args))
217 (apply #',name ,@args (first type) (rest type)))))
218
310da1d5 219
9adccb27 220(def-type-method alien-type ())
221(def-type-method size-of ())
222(def-type-method to-alien-form (form))
223(def-type-method from-alien-form (form))
224(def-type-method cleanup-form (form)
225 "Creates a form to clean up after the alien call has finished.")
310da1d5 226
9adccb27 227(def-type-method to-alien-function ())
228(def-type-method from-alien-function ())
229(def-type-method cleanup-function ())
310da1d5 230
9adccb27 231(def-type-method writer-function ())
232(def-type-method reader-function ())
233(def-type-method destroy-function ())
310da1d5 234
310da1d5 235
8755b1a5 236;; Sizes of fundamental C types in bytes (8 bits)
237(defconstant +size-of-short+ 2)
238(defconstant +size-of-int+ 4)
239(defconstant +size-of-long+ 4)
240(defconstant +size-of-pointer+ 4)
241(defconstant +size-of-float+ 4)
242(defconstant +size-of-double+ 8)
243
244;; Sizes of fundamental C types in bits
245(defconstant +bits-of-byte+ 8)
246(defconstant +bits-of-short+ 16)
247(defconstant +bits-of-int+ 32)
248(defconstant +bits-of-long+ 32)
249
250
9adccb27 251(deftype int () '(signed-byte #.+bits-of-int+))
252(deftype unsigned-int () '(unsigned-byte #.+bits-of-int+))
253(deftype long () '(signed-byte #.+bits-of-long+))
254(deftype unsigned-long () '(unsigned-byte #.+bits-of-long+))
255(deftype short () '(signed-byte #.+bits-of-short+))
256(deftype unsigned-short () '(unsigned-byte #.+bits-of-short+))
257(deftype signed (&optional (size '*)) `(signed-byte ,size))
258(deftype unsigned (&optional (size '*)) `(unsigned-byte ,size))
259(deftype char () 'base-char)
260(deftype pointer () 'system-area-pointer)
261(deftype boolean (&optional (size '*)) (declare (ignore size)) `(member t nil))
262;(deftype invalid () nil)
310da1d5 263
264
9adccb27 265(defmethod to-alien-form (form (type t) &rest args)
266 (declare (ignore type args))
267 form)
310da1d5 268
9adccb27 269(defmethod to-alien-function ((type t) &rest args)
270 (declare (ignore type args))
271 #'identity)
310da1d5 272
9adccb27 273(defmethod from-alien-form (form (type t) &rest args)
274 (declare (ignore type args))
275 form)
310da1d5 276
9adccb27 277(defmethod from-alien-function ((type t) &rest args)
278 (declare (ignore type args))
279 #'identity)
280
281(defmethod cleanup-form (form (type t) &rest args)
282 (declare (ignore form type args))
283 nil)
310da1d5 284
9adccb27 285(defmethod cleanup-function ((type t) &rest args)
286 (declare (ignore type args))
287 #'identity)
288
289(defmethod destroy-function ((type t) &rest args)
290 (declare (ignore type args))
291 #'(lambda (location offset)
292 (declare (ignore location offset))))
293
294
295(defmethod alien-type ((type (eql 'signed-byte)) &rest args)
296 (declare (ignore type))
297 (destructuring-bind (&optional (size '*)) args
298 (ecase size
299 (#.+bits-of-byte+ '(signed-byte 8))
300 (#.+bits-of-short+ 'c-call:short)
301 ((* #.+bits-of-int+) 'c-call:int)
302 (#.+bits-of-long+ 'c-call:long))))
303
304(defmethod size-of ((type (eql 'signed-byte)) &rest args)
305 (declare (ignore type))
306 (destructuring-bind (&optional (size '*)) args
307 (ecase size
308 (#.+bits-of-byte+ 1)
309 (#.+bits-of-short+ +size-of-short+)
310 ((* #.+bits-of-int+) +size-of-int+)
311 (#.+bits-of-long+ +size-of-long+))))
312
313(defmethod writer-function ((type (eql 'signed-byte)) &rest args)
314 (declare (ignore type))
315 (destructuring-bind (&optional (size '*)) args
316 (let ((size (if (eq size '*) +bits-of-int+ size)))
317 (ecase size
318 (8 #'(lambda (value location &optional (offset 0))
319 (setf (signed-sap-ref-8 location offset) value)))
320 (16 #'(lambda (value location &optional (offset 0))
321 (setf (signed-sap-ref-16 location offset) value)))
322 (32 #'(lambda (value location &optional (offset 0))
323 (setf (signed-sap-ref-32 location offset) value)))
324 (64 #'(lambda (value location &optional (offset 0))
325 (setf (signed-sap-ref-64 location offset) value)))))))
326
327(defmethod reader-function ((type (eql 'signed-byte)) &rest args)
328 (declare (ignore type))
329 (destructuring-bind (&optional (size '*)) args
330 (let ((size (if (eq size '*) +bits-of-int+ size)))
331 (ecase size
332 (8 #'(lambda (sap &optional (offset 0))
333 (signed-sap-ref-8 sap offset)))
334 (16 #'(lambda (sap &optional (offset 0))
335 (signed-sap-ref-16 sap offset)))
336 (32 #'(lambda (sap &optional (offset 0))
337 (signed-sap-ref-32 sap offset)))
338 (64 #'(lambda (sap &optional (offset 0))
339 (signed-sap-ref-64 sap offset)))))))
340
341(defmethod alien-type ((type (eql 'unsigned-byte)) &rest args)
342 (destructuring-bind (&optional (size '*)) args
343 (ecase size
344 (#.+bits-of-byte+ '(unsigned-byte 8))
345 (#.+bits-of-short+ 'c-call:unsigned-short)
346 ((* #.+bits-of-int+) 'c-call:unsigned-int)
347 (#.+bits-of-long+ 'c-call:unsigned-long))))
348
349(defmethod size-of ((type (eql 'unsigned-byte)) &rest args)
350 (apply #'size-of 'signed args))
351
352(defmethod writer-function ((type (eql 'unsigned-byte)) &rest args)
353 (declare (ignore type))
354 (destructuring-bind (&optional (size '*)) args
355 (let ((size (if (eq size '*) +bits-of-int+ size)))
356 (ecase size
357 (8 #'(lambda (value location &optional (offset 0))
358 (setf (sap-ref-8 location offset) value)))
359 (16 #'(lambda (value location &optional (offset 0))
360 (setf (sap-ref-16 location offset) value)))
361 (32 #'(lambda (value location &optional (offset 0))
362 (setf (sap-ref-32 location offset) value)))
363 (64 #'(lambda (value location &optional (offset 0))
364 (setf (sap-ref-64 location offset) value)))))))
365
366(defmethod reader-function ((type (eql 'unsigned-byte)) &rest args)
367 (declare (ignore type))
368 (destructuring-bind (&optional (size '*)) args
369 (let ((size (if (eq size '*) +bits-of-int+ size)))
370 (ecase size
371 (8 #'(lambda (sap &optional (offset 0))
372 (sap-ref-8 sap offset)))
373 (16 #'(lambda (sap &optional (offset 0))
374 (sap-ref-16 sap offset)))
375 (32 #'(lambda (sap &optional (offset 0))
376 (sap-ref-32 sap offset)))
377 (64 #'(lambda (sap &optional (offset 0))
378 (sap-ref-64 sap offset)))))))
379
380
381(defmethod alien-type ((type (eql 'integer)) &rest args)
382 (declare (ignore type args))
383 (alien-type 'signed-byte))
310da1d5 384
9adccb27 385(defmethod size-of ((type (eql 'integer)) &rest args)
386 (declare (ignore type args))
387 (size-of 'signed-byte))
310da1d5 388
310da1d5 389
9adccb27 390(defmethod alien-type ((type (eql 'fixnum)) &rest args)
391 (declare (ignore type args))
392 (alien-type 'signed-byte))
310da1d5 393
9adccb27 394(defmethod size-of ((type (eql 'fixnum)) &rest args)
395 (declare (ignore type args))
396 (size-of 'signed-byte))
310da1d5 397
398
9adccb27 399(defmethod alien-type ((type (eql 'single-float)) &rest args)
400 (declare (ignore type args))
401 'alien:single-float)
310da1d5 402
9adccb27 403(defmethod size-of ((type (eql 'single-float)) &rest args)
404 (declare (ignore type args))
310da1d5 405 +size-of-float+)
406
9adccb27 407(defmethod writer-function ((type (eql 'single-float)) &rest args)
408 (declare (ignore type args))
409 #'(lambda (value location &optional (offset 0))
8755b1a5 410 (setf (sap-ref-single location offset) (coerce value 'single-float))))
310da1d5 411
9adccb27 412(defmethod reader-function ((type (eql 'single-float)) &rest args)
413 (declare (ignore type args))
414 #'(lambda (sap &optional (offset 0))
415 (sap-ref-single sap offset)))
310da1d5 416
417
9adccb27 418(defmethod alien-type ((type (eql 'double-float)) &rest args)
419 (declare (ignore type args))
420 'alien:double-float)
310da1d5 421
9adccb27 422(defmethod size-of ((type (eql 'double-float)) &rest args)
423 (declare (ignore type args))
424 +size-of-float+)
310da1d5 425
9adccb27 426(defmethod writer-function ((type (eql 'double-float)) &rest args)
427 (declare (ignore type args))
428 #'(lambda (value location &optional (offset 0))
429 (setf (sap-ref-double location offset) (coerce value 'double-float))))
310da1d5 430
9adccb27 431(defmethod reader-function ((type (eql 'double-float)) &rest args)
432 (declare (ignore type args))
433 #'(lambda (sap &optional (offset 0))
434 (sap-ref-double sap offset)))
310da1d5 435
436
9adccb27 437(defmethod alien-type ((type (eql 'base-char)) &rest args)
438 (declare (ignore type args))
439 'c-call:char)
310da1d5 440
9adccb27 441(defmethod size-of ((type (eql 'base-char)) &rest args)
442 (declare (ignore type args))
310da1d5 443 1)
444
9adccb27 445(defmethod writer-function ((type (eql 'base-char)) &rest args)
446 (declare (ignore type args))
447 #'(lambda (char location &optional (offset 0))
448 (setf (sap-ref-8 location offset) (char-code char))))
310da1d5 449
9adccb27 450(defmethod reader-function ((type (eql 'base-char)) &rest args)
451 (declare (ignore type args))
452 #'(lambda (location &optional (offset 0))
453 (code-char (sap-ref-8 location offset))))
310da1d5 454
455
9adccb27 456(defmethod alien-type ((type (eql 'string)) &rest args)
457 (declare (ignore type args))
458 (alien-type 'pointer))
310da1d5 459
9adccb27 460(defmethod size-of ((type (eql 'string)) &rest args)
461 (declare (ignore type args))
462 (size-of 'pointer))
310da1d5 463
9adccb27 464(defmethod to-alien-form (string (type (eql 'string)) &rest args)
465 (declare (ignore type args))
310da1d5 466 `(let ((string ,string))
467 ;; Always copy strings to prevent seg fault due to GC
468 (copy-memory
469 (make-pointer (1+ (kernel:get-lisp-obj-address string)))
470 (1+ (length string)))))
310da1d5 471
9adccb27 472(defmethod to-alien-function ((type (eql 'string)) &rest args)
473 (declare (ignore type args))
474 #'(lambda (string)
475 (copy-memory
476 (make-pointer (1+ (kernel:get-lisp-obj-address string)))
477 (1+ (length string)))))
478
479(defmethod from-alien-form (string (type (eql 'string)) &rest args)
480 (declare (ignore type args))
481 `(let ((string ,string))
482 (unless (null-pointer-p string)
483 (c-call::%naturalize-c-string string))))
310da1d5 484
9adccb27 485(defmethod from-alien-function ((type (eql 'string)) &rest args)
486 (declare (ignore type args))
487 #'(lambda (string)
488 (unless (null-pointer-p string)
489 (c-call::%naturalize-c-string string))))
310da1d5 490
9adccb27 491(defmethod cleanup-form (string (type (eql 'string)) &rest args)
492 (declare (ignore type args))
493 `(let ((string ,string))
494 (unless (null-pointer-p string)
495 (deallocate-memory string))))
496
497(defmethod cleanup-function ((type (eql 'string)) &rest args)
8755b1a5 498 (declare (ignore args))
9adccb27 499 #'(lambda (string)
500 (unless (null-pointer-p string)
501 (deallocate-memory string))))
502
503(defmethod writer-function ((type (eql 'string)) &rest args)
504 (declare (ignore type args))
505 #'(lambda (string location &optional (offset 0))
506 (assert (null-pointer-p (sap-ref-sap location offset)))
507 (setf (sap-ref-sap location offset)
508 (copy-memory
509 (make-pointer (1+ (kernel:get-lisp-obj-address string)))
510 (1+ (length string))))))
511
512(defmethod reader-function ((type (eql 'string)) &rest args)
513 (declare (ignore type args))
514 #'(lambda (location &optional (offset 0))
515 (unless (null-pointer-p (sap-ref-sap location offset))
516 (c-call::%naturalize-c-string (sap-ref-sap location offset)))))
517
518(defmethod destroy-function ((type (eql 'string)) &rest args)
519 (declare (ignore type args))
520 #'(lambda (location &optional (offset 0))
521 (unless (null-pointer-p (sap-ref-sap location offset))
522 (deallocate-memory (sap-ref-sap location offset))
523 (setf (sap-ref-sap location offset) (make-pointer 0)))))
524
525
526(defmethod alien-type ((type (eql 'pathname)) &rest args)
527 (declare (ignore type args))
528 (alien-type 'string))
529
530(defmethod size-of ((type (eql 'pathname)) &rest args)
531 (declare (ignore type args))
532 (size-of 'string))
310da1d5 533
9adccb27 534(defmethod to-alien-form (path (type (eql 'pathname)) &rest args)
535 (declare (ignore type args))
536 (to-alien-form `(namestring (translate-logical-pathname ,path)) 'string))
537
538(defmethod to-alien-function ((type (eql 'pathname)) &rest args)
539 (declare (ignore type args))
540 (let ((string-function (to-alien-function 'string)))
541 #'(lambda (path)
542 (funcall string-function (namestring path)))))
543
544(defmethod from-alien-form (string (type (eql 'pathname)) &rest args)
545 (declare (ignore type args))
546 `(parse-namestring ,(from-alien-form string 'string)))
547
548(defmethod from-alien-function ((type (eql 'pathname)) &rest args)
549 (declare (ignore type args))
550 (let ((string-function (from-alien-function 'string)))
551 #'(lambda (string)
552 (parse-namestring (funcall string-function string)))))
553
554(defmethod cleanup-form (string (type (eql 'pathnanme)) &rest args)
555 (declare (ignore type args))
556 (cleanup-form string 'string))
557
558(defmethod cleanup-function ((type (eql 'pathnanme)) &rest args)
559 (declare (ignore type args))
560 (cleanup-function 'string))
561
562(defmethod writer-function ((type (eql 'pathname)) &rest args)
563 (declare (ignore type args))
564 (let ((string-writer (writer-function 'string)))
565 #'(lambda (path location &optional (offset 0))
566 (funcall string-writer (namestring path) location offset))))
567
568(defmethod reader-function ((type (eql 'pathname)) &rest args)
569 (declare (ignore type args))
570 (let ((string-reader (reader-function 'string)))
571 #'(lambda (location &optional (offset 0))
572 (let ((string (funcall string-reader location offset)))
573 (when string
574 (parse-namestring string))))))
575
576(defmethod destroy-function ((type (eql 'pathname)) &rest args)
577 (declare (ignore type args))
578 (destroy-function 'string))
579
580
581(defmethod alien-type ((type (eql 'boolean)) &rest args)
582 (apply #'alien-type 'signed-byte args))
583
584(defmethod size-of ((type (eql 'boolean)) &rest args)
585 (apply #'size-of 'signed-byte args))
586
587(defmethod to-alien-form (boolean (type (eql 'boolean)) &rest args)
588 (declare (ignore type args))
310da1d5 589 `(if ,boolean 1 0))
590
9adccb27 591(defmethod to-alien-function ((type (eql 'boolean)) &rest args)
592 (declare (ignore type args))
593 #'(lambda (boolean)
594 (if boolean 1 0)))
595
596(defmethod from-alien-form (boolean (type (eql 'boolean)) &rest args)
597 (declare (ignore type args))
598 `(not (zerop ,boolean)))
599
600(defmethod from-alien-function ((type (eql 'boolean)) &rest args)
601 (declare (ignore type args))
602 #'(lambda (boolean)
603 (not (zerop boolean))))
604
605(defmethod writer-function ((type (eql 'boolean)) &rest args)
606 (declare (ignore type))
607 (let ((writer (apply #'writer-function 'signed-byte args)))
608 #'(lambda (boolean location &optional (offset 0))
609 (funcall writer (if boolean 1 0) location offset))))
610
611(defmethod reader-function ((type (eql 'boolean)) &rest args)
612 (declare (ignore type))
613 (let ((reader (apply #'reader-function 'signed-byte args)))
614 #'(lambda (location &optional (offset 0))
615 (not (zerop (funcall reader location offset))))))
616
617
618(defmethod alien-type ((type (eql 'or)) &rest args)
619 (let ((alien-type (alien-type (first args))))
620 (unless (every #'(lambda (type)
621 (eq alien-type (alien-type type)))
622 (rest args))
623 (error "No common alien type specifier for union type: ~A"
624 (cons type args)))
310da1d5 625 alien-type))
626
9adccb27 627(defmethod size-of ((type (eql 'or)) &rest args)
628 (declare (ignore type))
629 (size-of (first args)))
630
631(defmethod to-alien-form (form (type (eql 'or)) &rest args)
632 (declare (ignore type))
633 `(let ((value ,form))
634 (etypecase value
635 ,@(mapcar
636 #'(lambda (type)
637 `(,type ,(to-alien-form 'value type)))
638 args))))
639
640(defmethod to-alien-function ((type (eql 'or)) &rest types)
641 (declare (ignore type))
642 (let ((functions (mapcar #'to-alien-function types)))
643 #'(lambda (value)
644 (loop
645 for function in functions
646 for type in types
647 when (typep value type)
648 do (return (funcall function value))
649 finally (error "~S is not of type ~A" value `(or ,@types))))))
650
651(defmethod alien-type ((type (eql 'system-area-pointer)) &rest args)
652 (declare (ignore type args))
310da1d5 653 'system-area-pointer)
654
9adccb27 655(defmethod size-of ((type (eql 'system-area-pointer)) &rest args)
656 (declare (ignore type args))
657 +size-of-pointer+)
310da1d5 658
9adccb27 659(defmethod writer-function ((type (eql 'system-area-pointer)) &rest args)
660 (declare (ignore type args))
661 #'(lambda (sap location &optional (offset 0))
662 (setf (sap-ref-sap location offset) sap)))
310da1d5 663
9adccb27 664(defmethod reader-function ((type (eql 'system-area-pointer)) &rest args)
665 (declare (ignore type args))
666 #'(lambda (location &optional (offset 0))
667 (sap-ref-sap location offset)))
310da1d5 668
669
9adccb27 670(defmethod alien-type ((type (eql 'null)) &rest args)
671 (declare (ignore type args))
672 (alien-type 'pointer))
310da1d5 673
9adccb27 674(defmethod size-of ((type (eql 'null)) &rest args)
675 (declare (ignore type args))
676 (size-of 'pointer))
677
678(defmethod to-alien-form (null (type (eql 'null)) &rest args)
679 (declare (ignore null type args))
310da1d5 680 `(make-pointer 0))
681
9adccb27 682(defmethod to-alien-function ((type (eql 'null)) &rest args)
683 (declare (ignore type args))
684 #'(lambda (null)
685 (declare (ignore null))
686 (make-pointer 0)))
310da1d5 687
310da1d5 688
9adccb27 689(defmethod alien-type ((type (eql 'nil)) &rest args)
690 (declare (ignore type args))
691 'c-call:void)
692
693(defmethod from-alien-function ((type (eql 'nil)) &rest args)
694 (declare (ignore type args))
695 #'(lambda (value)
696 (declare (ignore value))
697 (values)))