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.26 2006-02-26 15:30:00 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 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 type var)))
131 ((member style '(:out :in-out))
132 (alien-types `(* ,declaration))
133 (alien-parameters `(addr ,var))
137 ((eq style :in-out) (list (to-alien-form type expr)))
138 ((eq declaration 'system-area-pointer)
139 (list '(make-pointer 0))))))
140 (return-values (from-alien-form type var)))
142 (alien-types declaration)
144 `(,var ,declaration ,(to-alien-form type expr)))
145 (alien-parameters var)
146 (return-values (from-alien-form type var)))
148 (alien-types declaration)
150 `(,var ,declaration ,(to-alien-form type expr)))
151 (alien-parameters var)
152 (cleanup-forms cleanup))
154 (alien-types declaration)
155 (alien-parameters (to-alien-form type expr)))))))
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 return-type alien-funcall)
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)))
226 #+cmu(defparameter ,name nil)
227 (,define-callback ,name
228 #+(and sbcl alien-callbacks),(alien-type return-type)
229 (#+(or cmu (and sbcl (not alien-callbacks))),(alien-type return-type)
230 ,@(mapcar #'(lambda (arg)
231 (destructuring-bind (name type) arg
232 `(,name ,(alien-type type))))
234 ,@(when doc (list doc))
235 ,(to-alien-form return-type
237 for (name type) in args
238 as from-alien-form = (callback-from-alien-form type name)
239 collect `(,name ,from-alien-form)))
240 ,@(when declaration (list declaration))
244 for (name type) in args
245 do (callback-cleanup-form type name))))))))))
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 ;;;; The "type method" system
271 (defun find-applicable-type-method (name type-spec &optional (error-p t))
272 (let ((type-methods (get name 'type-methods)))
273 (labels ((search-method-in-cpl-order (classes)
276 (gethash (class-name (first classes)) type-methods)
277 (search-method-in-cpl-order (rest classes)))))
278 (lookup-method (type-spec)
279 (if (and (symbolp type-spec) (find-class type-spec nil))
280 (search-method-in-cpl-order
281 (class-precedence-list (find-class type-spec)))
283 (let ((specifier (etypecase type-spec
285 (list (first type-spec)))))
286 (gethash specifier type-methods))
287 (multiple-value-bind (expanded-type expanded-p)
288 (type-expand-1 type-spec)
290 (lookup-method expanded-type))))))
291 (search-built-in-type-hierarchy (sub-tree)
292 (when (subtypep type-spec (first sub-tree))
294 (search-nodes (cddr sub-tree))
296 (search-nodes (nodes)
299 as function = (search-built-in-type-hierarchy node)
301 finally (return function))))
303 (lookup-method type-spec)
304 ;; This is to handle unexpandable types whichs doesn't name a class
305 (unless (and (symbolp type-spec) (find-class type-spec nil))
306 (search-nodes (get name 'built-in-type-hierarchy)))
309 (error "No applicable type method for ~A when call width type specifier ~A" name type-spec))))))
312 (defun insert-type-in-hierarchy (specifier function nodes)
314 ((let ((node (find specifier nodes :key #'first)))
316 (setf (second node) function)
321 (subtypep specifier (first node)))
325 (insert-type-in-hierarchy specifier function (cddr node)))
327 ((let ((sub-nodes (remove-if-not
329 (subtypep (first node) specifier))
332 (list* specifier function sub-nodes)
333 (nset-difference nodes sub-nodes))))))
336 (defun add-type-method (name specifier function)
337 (setf (gethash specifier (get name 'type-methods)) function)
338 (when (typep (find-class specifier nil) 'built-in-class)
339 (setf (get name 'built-in-type-hierarchy)
340 (insert-type-in-hierarchy specifier function
341 (get name 'built-in-type-hierarchy)))))
344 ;; TODO: handle optional, key and rest arguments
345 (defmacro define-type-generic (name lambda-list &optional documentation)
348 (find (first lambda-list) '(&optional &key &rest &allow-other-keys)))
349 (error "A type generic needs at least one required argument")
351 (setf (get ',name 'type-methods) (make-hash-table))
352 (setf (get ',name 'built-in-type-hierarchy) ())
353 (defun ,name ,lambda-list
356 (find-applicable-type-method ',name ,(first lambda-list))
360 (defmacro define-type-method (name lambda-list &body body)
361 (let ((specifier (cadar lambda-list))
362 (args (cons (caar lambda-list) (rest lambda-list))))
364 (add-type-method ',name ',specifier #'(lambda ,args ,@body))
369 ;;;; Definitons and translations of fundamental types
371 (define-type-generic alien-type (type-spec))
372 (define-type-generic size-of (type-spec))
373 (define-type-generic to-alien-form (type-spec form))
374 (define-type-generic from-alien-form (type-spec form))
375 (define-type-generic cleanup-form (type-spec form)
376 "Creates a form to clean up after the alien call has finished.")
377 (define-type-generic callback-from-alien-form (type-spec form))
378 (define-type-generic callback-cleanup-form (type-spec form))
380 (define-type-generic to-alien-function (type-spec))
381 (define-type-generic from-alien-function (type-spec))
382 (define-type-generic cleanup-function (type-spec))
384 (define-type-generic copy-to-alien-form (type-spec form))
385 (define-type-generic copy-to-alien-function (type-spec))
386 (define-type-generic copy-from-alien-form (type-spec form))
387 (define-type-generic copy-from-alien-function (type-spec))
388 (define-type-generic writer-function (type-spec))
389 (define-type-generic reader-function (type-spec))
390 (define-type-generic destroy-function (type-spec))
392 (define-type-generic unbound-value (type-spec)
393 "Returns a value which should be intepreted as unbound for slots with virtual allocation")
396 ;; Sizes of fundamental C types in bytes (8 bits)
397 (defconstant +size-of-short+ 2)
398 (defconstant +size-of-int+ 4)
399 (defconstant +size-of-long+ 4)
400 (defconstant +size-of-pointer+ 4)
401 (defconstant +size-of-float+ 4)
402 (defconstant +size-of-double+ 8)
404 ;; Sizes of fundamental C types in bits
405 (defconstant +bits-of-byte+ 8)
406 (defconstant +bits-of-short+ 16)
407 (defconstant +bits-of-int+ 32)
408 (defconstant +bits-of-long+ 32)
411 (deftype int () '(signed-byte #.+bits-of-int+))
412 (deftype unsigned-int () '(unsigned-byte #.+bits-of-int+))
413 (deftype long () '(signed-byte #.+bits-of-long+))
414 (deftype unsigned-long () '(unsigned-byte #.+bits-of-long+))
415 (deftype short () '(signed-byte #.+bits-of-short+))
416 (deftype unsigned-short () '(unsigned-byte #.+bits-of-short+))
417 (deftype signed (&optional (size '*)) `(signed-byte ,size))
418 (deftype unsigned (&optional (size '*)) `(unsigned-byte ,size))
419 (deftype char () 'base-char)
420 (deftype pointer () 'system-area-pointer)
421 (deftype boolean (&optional (size '*)) (declare (ignore size)) t)
422 (deftype copy-of (type) type)
424 (define-type-method alien-type ((type t))
425 (error "No alien type corresponding to the type specifier ~A" type))
427 (define-type-method to-alien-form ((type t) form)
428 (declare (ignore form))
429 (error "Not a valid type specifier for arguments: ~A" type))
431 (define-type-method to-alien-function ((type t))
432 (error "Not a valid type specifier for arguments: ~A" type))
434 (define-type-method from-alien-form ((type t) form)
435 (declare (ignore form))
436 (error "Not a valid type specifier for return values: ~A" type))
438 (define-type-method from-alien-function ((type t))
439 (error "Not a valid type specifier for return values: ~A" type))
441 (define-type-method cleanup-form ((type t) form)
442 (declare (ignore form type))
445 (define-type-method cleanup-function ((type t))
446 (declare (ignore type))
449 (define-type-method callback-from-alien-form ((type t) form)
450 (copy-from-alien-form type form))
452 (define-type-method callback-cleanup-form ((type t) form)
453 (declare (ignore form type))
456 (define-type-method destroy-function ((type t))
457 (declare (ignore type))
458 #'(lambda (location &optional offset)
459 (declare (ignore location offset))))
461 (define-type-method copy-to-alien-form ((type t) form)
462 (to-alien-form type form))
464 (define-type-method copy-to-alien-function ((type t))
465 (to-alien-function type))
467 (define-type-method copy-from-alien-form ((type t) form)
468 (from-alien-form type form))
470 (define-type-method copy-from-alien-function ((type t))
471 (from-alien-function type))
474 (define-type-method to-alien-form ((type real) form)
475 (declare (ignore type))
478 (define-type-method to-alien-function ((type real))
479 (declare (ignore type))
482 (define-type-method from-alien-form ((type real) form)
483 (declare (ignore type))
486 (define-type-method from-alien-function ((type real))
487 (declare (ignore type))
491 (define-type-method alien-type ((type integer))
492 (declare (ignore type))
493 (alien-type 'signed-byte))
495 (define-type-method size-of ((type integer))
496 (declare (ignore type))
497 (size-of 'signed-byte))
499 (define-type-method writer-function ((type integer))
500 (declare (ignore type))
501 (writer-function 'signed-byte))
503 (define-type-method reader-function ((type integer))
504 (declare (ignore type))
505 (reader-function 'signed-byte))
508 (define-type-method alien-type ((type signed-byte))
509 (destructuring-bind (&optional (size '*))
510 (rest (mklist (type-expand-to 'signed-byte type)))
512 (#.+bits-of-byte+ #+cmu'(alien:signed 8) #+sbcl'(sb-alien:signed 8))
513 (#.+bits-of-short+ #+cmu 'c-call:short #+sbcl 'sb-alien:short)
514 ((* #.+bits-of-int+) #+cmu 'c-call:int #+sbcl 'sb-alien:int)
515 (#.+bits-of-long+ #+cmu 'c-call:long #+sbcl 'sb-alien:long))))
517 (define-type-method size-of ((type signed-byte))
518 (destructuring-bind (&optional (size '*))
519 (rest (mklist (type-expand-to 'signed-byte type)))
522 (#.+bits-of-short+ +size-of-short+)
523 ((* #.+bits-of-int+) +size-of-int+)
524 (#.+bits-of-long+ +size-of-long+))))
526 (define-type-method writer-function ((type signed-byte))
527 (destructuring-bind (&optional (size '*))
528 (rest (mklist (type-expand-to 'signed-byte type)))
529 (let ((size (if (eq size '*) +bits-of-int+ size)))
531 (8 #'(lambda (value location &optional (offset 0))
532 (setf (signed-sap-ref-8 location offset) value)))
533 (16 #'(lambda (value location &optional (offset 0))
534 (setf (signed-sap-ref-16 location offset) value)))
535 (32 #'(lambda (value location &optional (offset 0))
536 (setf (signed-sap-ref-32 location offset) value)))
537 (64 #'(lambda (value location &optional (offset 0))
538 (setf (signed-sap-ref-64 location offset) value)))))))
540 (define-type-method reader-function ((type signed-byte))
541 (destructuring-bind (&optional (size '*))
542 (rest (mklist (type-expand-to 'signed-byte type)))
543 (let ((size (if (eq size '*) +bits-of-int+ size)))
545 (8 #'(lambda (sap &optional (offset 0) weak-p)
546 (declare (ignore weak-p))
547 (signed-sap-ref-8 sap offset)))
548 (16 #'(lambda (sap &optional (offset 0) weak-p)
549 (declare (ignore weak-p))
550 (signed-sap-ref-16 sap offset)))
551 (32 #'(lambda (sap &optional (offset 0) weak-p)
552 (declare (ignore weak-p))
553 (signed-sap-ref-32 sap offset)))
554 (64 #'(lambda (sap &optional (offset 0) weak-p)
555 (declare (ignore weak-p))
556 (signed-sap-ref-64 sap offset)))))))
559 (define-type-method alien-type ((type unsigned-byte))
560 (destructuring-bind (&optional (size '*))
561 (rest (mklist (type-expand-to 'unsigned-byte type)))
563 (#.+bits-of-byte+ #+cmu'(alien:unsigned 8) #+sbcl'(sb-alien:unsigned 8))
564 (#.+bits-of-short+ #+cmu 'c-call:unsigned-short
565 #+sbcl 'sb-alien:unsigned-short)
566 ((* #.+bits-of-int+) #+cmu 'c-call:unsigned-int
567 #+sbcl 'sb-alien:unsigned-int)
568 (#.+bits-of-long+ #+cmu 'c-call:unsigned-long
569 #+sbcl 'sb-alien:unsigned-long))))
572 (define-type-method size-of ((type unsigned-byte))
573 (destructuring-bind (&optional (size '*))
574 (rest (mklist (type-expand-to 'unsigned-byte type)))
575 (size-of `(signed ,size))))
577 (define-type-method writer-function ((type unsigned-byte))
578 (destructuring-bind (&optional (size '*))
579 (rest (mklist (type-expand-to 'unsigned-byte type)))
580 (let ((size (if (eq size '*) +bits-of-int+ size)))
582 (8 #'(lambda (value location &optional (offset 0))
583 (setf (sap-ref-8 location offset) value)))
584 (16 #'(lambda (value location &optional (offset 0))
585 (setf (sap-ref-16 location offset) value)))
586 (32 #'(lambda (value location &optional (offset 0))
587 (setf (sap-ref-32 location offset) value)))
588 (64 #'(lambda (value location &optional (offset 0))
589 (setf (sap-ref-64 location offset) value)))))))
591 (define-type-method reader-function ((type unsigned-byte))
592 (destructuring-bind (&optional (size '*))
593 (rest (mklist (type-expand-to 'unsigned-byte type)))
594 (let ((size (if (eq size '*) +bits-of-int+ size)))
596 (8 #'(lambda (sap &optional (offset 0) weak-p)
597 (declare (ignore weak-p))
598 (sap-ref-8 sap offset)))
599 (16 #'(lambda (sap &optional (offset 0) weak-p)
600 (declare (ignore weak-p))
601 (sap-ref-16 sap offset)))
602 (32 #'(lambda (sap &optional (offset 0) weak-p)
603 (declare (ignore weak-p))
604 (sap-ref-32 sap offset)))
605 (64 #'(lambda (sap &optional (offset 0) weak-p)
606 (declare (ignore weak-p))
607 (sap-ref-64 sap offset)))))))
609 (define-type-method alien-type ((type single-float))
610 (declare (ignore type))
611 #+cmu 'alien:single-float #+sbcl 'sb-alien:single-float)
613 (define-type-method size-of ((type single-float))
614 (declare (ignore type))
617 (define-type-method to-alien-form ((type single-float) form)
618 (declare (ignore type))
619 `(coerce ,form 'single-float))
621 (define-type-method to-alien-function ((type single-float))
622 (declare (ignore type))
624 (coerce number 'single-float)))
626 (define-type-method writer-function ((type single-float))
627 (declare (ignore type))
628 #'(lambda (value location &optional (offset 0))
629 (setf (sap-ref-single location offset) (coerce value 'single-float))))
631 (define-type-method reader-function ((type single-float))
632 (declare (ignore type))
633 #'(lambda (sap &optional (offset 0) weak-p)
634 (declare (ignore weak-p))
635 (sap-ref-single sap offset)))
638 (define-type-method alien-type ((type double-float))
639 (declare (ignore type))
640 #+cmu 'alien:double-float #+sbcl 'sb-alien:double-float)
642 (define-type-method size-of ((type double-float))
643 (declare (ignore type))
646 (define-type-method to-alien-form ((type double-float) form)
647 (declare (ignore type))
648 `(coerce ,form 'double-float))
650 (define-type-method to-alien-function ((type double-float))
651 (declare (ignore type))
653 (coerce number 'double-float)))
655 (define-type-method writer-function ((type double-float))
656 (declare (ignore type))
657 #'(lambda (value location &optional (offset 0))
658 (setf (sap-ref-double location offset) (coerce value 'double-float))))
660 (define-type-method reader-function ((type double-float))
661 (declare (ignore type))
662 #'(lambda (sap &optional (offset 0) weak-p)
663 (declare (ignore weak-p))
664 (sap-ref-double sap offset)))
667 (define-type-method alien-type ((type base-char))
668 (declare (ignore type))
669 #+cmu 'c-call:char #+sbcl 'sb-alien:char)
671 (define-type-method size-of ((type base-char))
672 (declare (ignore type))
675 (define-type-method to-alien-form ((type base-char) form)
676 (declare (ignore type))
679 (define-type-method to-alien-function ((type base-char))
680 (declare (ignore type))
683 (define-type-method from-alien-form ((type base-char) form)
684 (declare (ignore type))
687 (define-type-method from-alien-function ((type base-char))
688 (declare (ignore type))
691 (define-type-method writer-function ((type base-char))
692 (declare (ignore type))
693 #'(lambda (char location &optional (offset 0))
694 (setf (sap-ref-8 location offset) (char-code char))))
696 (define-type-method reader-function ((type base-char))
697 (declare (ignore type))
698 #'(lambda (location &optional (offset 0) weak-p)
699 (declare (ignore weak-p))
700 (code-char (sap-ref-8 location offset))))
703 (define-type-method alien-type ((type string))
704 (declare (ignore type))
705 (alien-type 'pointer))
707 (define-type-method size-of ((type string))
708 (declare (ignore type))
711 (define-type-method to-alien-form ((type string) string)
712 (declare (ignore type))
713 `(let ((string ,string))
714 ;; Always copy strings to prevent seg fault due to GC
717 (vector-sap (coerce string 'simple-base-string))
718 (1+ (length string)))
720 (let ((utf8 (%deport-utf8-string string)))
721 (copy-memory (vector-sap utf8) (length utf8)))))
723 (define-type-method to-alien-function ((type string))
724 (declare (ignore type))
728 (vector-sap (coerce string 'simple-base-string))
729 (1+ (length string)))
731 (let ((utf8 (%deport-utf8-string string)))
732 (copy-memory (vector-sap utf8) (length utf8)))))
734 (define-type-method from-alien-form ((type string) string)
735 (declare (ignore type))
736 `(let ((string ,string))
737 (unless (null-pointer-p string)
739 #+cmu(%naturalize-c-string string)
740 #+sbcl(%naturalize-utf8-string string)
741 (deallocate-memory string)))))
743 (define-type-method from-alien-function ((type string))
744 (declare (ignore type))
746 (unless (null-pointer-p string)
748 #+cmu(%naturalize-c-string string)
749 #+sbcl(%naturalize-utf8-string string)
750 (deallocate-memory string)))))
752 (define-type-method cleanup-form ((type string) string)
753 (declare (ignore type))
754 `(let ((string ,string))
755 (unless (null-pointer-p string)
756 (deallocate-memory string))))
758 (define-type-method cleanup-function ((type string))
759 (declare (ignore type))
761 (unless (null-pointer-p string)
762 (deallocate-memory string))))
764 (define-type-method copy-from-alien-form ((type string) string)
765 (declare (ignore type))
766 `(let ((string ,string))
767 (unless (null-pointer-p string)
768 #+cmu(%naturalize-c-string string)
769 #+sbcl(%naturalize-utf8-string string))))
771 (define-type-method copy-from-alien-function ((type string))
772 (declare (ignore type))
774 (unless (null-pointer-p string)
775 #+cmu(%naturalize-c-string string)
776 #+sbcl(%naturalize-utf8-string string))))
778 (define-type-method writer-function ((type string))
779 (declare (ignore type))
780 #'(lambda (string location &optional (offset 0))
781 (assert (null-pointer-p (sap-ref-sap location offset)))
782 (setf (sap-ref-sap location offset)
785 (vector-sap (coerce string 'simple-base-string))
786 (1+ (length string)))
788 (let ((utf8 (%deport-utf8-string string)))
789 (copy-memory (vector-sap utf8) (length utf8))))))
791 (define-type-method reader-function ((type string))
792 (declare (ignore type))
793 #'(lambda (location &optional (offset 0) weak-p)
794 (declare (ignore weak-p))
795 (unless (null-pointer-p (sap-ref-sap location offset))
796 #+cmu(%naturalize-c-string (sap-ref-sap location offset))
797 #+sbcl(%naturalize-utf8-string (sap-ref-sap location offset)))))
799 (define-type-method destroy-function ((type string))
800 (declare (ignore type))
801 #'(lambda (location &optional (offset 0))
802 (unless (null-pointer-p (sap-ref-sap location offset))
803 (deallocate-memory (sap-ref-sap location offset))
804 (setf (sap-ref-sap location offset) (make-pointer 0)))))
806 (define-type-method unbound-value ((type string))
807 (declare (ignore type))
811 (define-type-method alien-type ((type pathname))
812 (declare (ignore type))
813 (alien-type 'string))
815 (define-type-method size-of ((type pathname))
816 (declare (ignore type))
819 (define-type-method to-alien-form ((type pathname) path)
820 (declare (ignore type))
821 (to-alien-form 'string `(namestring (translate-logical-pathname ,path))))
823 (define-type-method to-alien-function ((type pathname))
824 (declare (ignore type))
825 (let ((string-function (to-alien-function 'string)))
827 (funcall string-function (namestring path)))))
829 (define-type-method from-alien-form ((type pathname) string)
830 (declare (ignore type))
831 `(parse-namestring ,(from-alien-form 'string string)))
833 (define-type-method from-alien-function ((type pathname))
834 (declare (ignore type))
835 (let ((string-function (from-alien-function 'string)))
837 (parse-namestring (funcall string-function string)))))
839 (define-type-method cleanup-form ((type pathnanme) string)
840 (declare (ignore type))
841 (cleanup-form 'string string))
843 (define-type-method cleanup-function ((type pathnanme))
844 (declare (ignore type))
845 (cleanup-function 'string))
847 (define-type-method writer-function ((type pathname))
848 (declare (ignore type))
849 (let ((string-writer (writer-function 'string)))
850 #'(lambda (path location &optional (offset 0))
851 (funcall string-writer (namestring path) location offset))))
853 (define-type-method reader-function ((type pathname))
854 (declare (ignore type))
855 (let ((string-reader (reader-function 'string)))
856 #'(lambda (location &optional (offset 0) weak-p)
857 (declare (ignore weak-p))
858 (let ((string (funcall string-reader location offset)))
860 (parse-namestring string))))))
862 (define-type-method destroy-function ((type pathname))
863 (declare (ignore type))
864 (destroy-function 'string))
866 (define-type-method unbound-value ((type pathname))
867 (declare (ignore type))
868 (unbound-value 'string))
871 (define-type-method alien-type ((type boolean))
872 (destructuring-bind (&optional (size '*))
873 (rest (mklist (type-expand-to 'boolean type)))
874 (alien-type `(signed-byte ,size))))
876 (define-type-method size-of ((type boolean))
877 (destructuring-bind (&optional (size '*))
878 (rest (mklist (type-expand-to 'boolean type)))
879 (size-of `(signed-byte ,size))))
881 (define-type-method to-alien-form ((type boolean) boolean)
882 (declare (ignore type))
885 (define-type-method to-alien-function ((type boolean))
886 (declare (ignore type))
890 (define-type-method from-alien-form ((type boolean) boolean)
891 (declare (ignore type))
892 `(not (zerop ,boolean)))
894 (define-type-method from-alien-function ((type boolean))
895 (declare (ignore type))
897 (not (zerop boolean))))
899 (define-type-method writer-function ((type boolean))
900 (destructuring-bind (&optional (size '*))
901 (rest (mklist (type-expand-to 'boolean type)))
902 (let ((writer (writer-function `(signed-byte ,size))))
903 #'(lambda (boolean location &optional (offset 0))
904 (funcall writer (if boolean 1 0) location offset)))))
906 (define-type-method reader-function ((type boolean))
907 (destructuring-bind (&optional (size '*))
908 (rest (mklist (type-expand-to 'boolean type)))
909 (let ((reader (reader-function `(signed-byte ,size))))
910 #'(lambda (location &optional (offset 0) weak-p)
911 (declare (ignore weak-p))
912 (not (zerop (funcall reader location offset)))))))
915 (define-type-method alien-type ((type or))
916 (let* ((expanded-type (type-expand-to 'or type))
917 (alien-type (alien-type (second expanded-type))))
918 (unless (every #'(lambda (type)
919 (eq alien-type (alien-type type)))
920 (cddr expanded-type))
921 (error "No common alien type specifier for union type: ~A" type))
924 (define-type-method size-of ((type or))
925 (size-of (second (type-expand-to 'or type))))
927 (define-type-method to-alien-form ((type or) form)
928 `(let ((value ,form))
932 `(,type ,(to-alien-form type 'value)))
933 (rest (type-expand-to 'or type))))))
935 (define-type-method to-alien-function ((type or))
936 (let* ((expanded-type (type-expand-to 'or type))
937 (functions (mapcar #'to-alien-function (rest expanded-type))))
940 for function in functions
941 for alt-type in (rest expanded-type)
942 when (typep value alt-type)
943 do (return (funcall function value))
944 finally (error "~S is not of type ~A" value type)))))
947 (define-type-method alien-type ((type pointer))
948 (declare (ignore type))
949 'system-area-pointer)
951 (define-type-method size-of ((type pointer))
952 (declare (ignore type))
955 (define-type-method to-alien-form ((type pointer) form)
956 (declare (ignore type))
959 (define-type-method to-alien-function ((type pointer))
960 (declare (ignore type))
963 (define-type-method from-alien-form ((type pointer) form)
964 (declare (ignore type))
967 (define-type-method from-alien-function ((type pointer))
968 (declare (ignore type))
971 (define-type-method writer-function ((type pointer))
972 (declare (ignore type))
973 #'(lambda (sap location &optional (offset 0))
974 (setf (sap-ref-sap location offset) sap)))
976 (define-type-method reader-function ((type pointer))
977 (declare (ignore type))
978 #'(lambda (location &optional (offset 0) weak-p)
979 (declare (ignore weak-p))
980 (sap-ref-sap location offset)))
983 (define-type-method alien-type ((type null))
984 (declare (ignore type))
985 (alien-type 'pointer))
987 (define-type-method size-of ((type null))
988 (declare (ignore type))
991 (define-type-method to-alien-form ((type null) null)
992 (declare (ignore null type))
995 (define-type-method to-alien-function ((type null))
996 (declare (ignore type))
998 (declare (ignore null))
1002 (define-type-method alien-type ((type nil))
1003 (declare (ignore type))
1006 (define-type-method from-alien-function ((type nil))
1007 (declare (ignore type))
1009 (declare (ignore value))
1012 (define-type-method to-alien-form ((type nil) form)
1013 (declare (ignore type))
1017 (define-type-method to-alien-form ((type copy-of) form)
1018 (copy-to-alien-form (second (type-expand-to 'copy-of type)) form))
1020 (define-type-method to-alien-function ((type copy-of))
1021 (copy-to-alien-function (second (type-expand-to 'copy-of type))))
1023 (define-type-method from-alien-form ((type copy-of) form)
1024 (copy-from-alien-form (second (type-expand-to 'copy-of type)) form))
1026 (define-type-method from-alien-function ((type copy-of))
1027 (copy-from-alien-function (second (type-expand-to 'copy-of type))))
1030 (define-type-method alien-type ((type callback))
1031 (declare (ignore type))
1032 (alien-type 'pointer))
1034 (define-type-method to-alien-form ((type callback) callback)
1035 (declare (ignore type ))
1036 `(callback-address ,callback))