chiark / gitweb /
Type for callback ids changes to POINTER-DATA
[clg] / glib / gtype.lisp
CommitLineData
55212af1 1;; Common Lisp bindings for GTK+ v2.x
08cb5756 2;; Copyright 2000-2006 Espen S. Johnsen <espen@users.sf.net>
0d07716f 3;;
55212af1 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:
0d07716f 11;;
55212af1 12;; The above copyright notice and this permission notice shall be
13;; included in all copies or substantial portions of the Software.
0d07716f 14;;
55212af1 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.
22
8ac82923 23;; $Id: gtype.lisp,v 1.60 2007/01/12 10:32:43 espen Exp $
0d07716f 24
25(in-package "GLIB")
26
27(use-prefix "g")
28
d1266407 29;; Initialize the glib type system
30(defbinding type-init () nil)
31(type-init)
0d07716f 32
fb9bc912 33(deftype type-number () 'unsigned-long)
0d07716f 34
b4a2c852 35(deftype gtype () 'symbol)
36
4d1fea77 37(define-type-method alien-type ((type gtype))
38 (declare (ignore type))
b4a2c852 39 (alien-type 'type-number))
40
08cb5756 41(define-type-method size-of ((type gtype) &key (inlined t))
42 (assert-inlined type inlined)
b4a2c852 43 (size-of 'type-number))
44
08cb5756 45(define-type-method to-alien-form ((type gtype) gtype &optional copy-p)
46 (declare (ignore type copy-p))
b4a2c852 47 `(find-type-number ,gtype t))
48
08cb5756 49(define-type-method to-alien-function ((type gtype) &optional copy-p)
50 (declare (ignore type copy-p))
b4a2c852 51 #'(lambda (gtype)
52 (find-type-number gtype t)))
53
08cb5756 54(define-type-method from-alien-form ((type gtype) form &key ref)
55 (declare (ignore type ref))
56 `(type-from-number ,form))
b4a2c852 57
08cb5756 58(define-type-method from-alien-function ((type gtype) &key ref)
59 (declare (ignore type ref))
b4a2c852 60 #'(lambda (type-number)
40c346ec 61 (type-from-number type-number)))
b4a2c852 62
08cb5756 63(define-type-method writer-function ((type gtype) &key temp (inlined t))
64 (declare (ignore temp))
65 (assert-inlined type inlined)
b4a2c852 66 (let ((writer (writer-function 'type-number)))
67 #'(lambda (gtype location &optional (offset 0))
68 (funcall writer (find-type-number gtype t) location offset))))
69
08cb5756 70(define-type-method reader-function ((type gtype) &key ref (inlined t))
71 (declare (ignore ref))
72 (assert-inlined type inlined)
b4a2c852 73 (let ((reader (reader-function 'type-number)))
08cb5756 74 #'(lambda (location &optional (offset 0))
40c346ec 75 (type-from-number (funcall reader location offset)))))
b4a2c852 76
77
fc47a022 78(eval-when (:compile-toplevel :load-toplevel :execute)
3a935dfa 79 (defclass type-query (struct)
fc47a022 80 ((type-number :allocation :alien :type type-number)
08cb5756 81 (name :allocation :alien :type (copy-of string))
fc47a022 82 (class-size :allocation :alien :type unsigned-int)
83 (instance-size :allocation :alien :type unsigned-int))
4d1d3921 84 (:metaclass struct-class)))
fc47a022 85
86
b4a2c852 87(defbinding type-query (type) nil
88 ((find-type-number type t) type-number)
08cb5756 89 ((make-instance 'type-query) type-query :in/return))
fc47a022 90
91(defun type-instance-size (type)
92 (slot-value (type-query type) 'instance-size))
93
94(defun type-class-size (type)
95 (slot-value (type-query type) 'class-size))
0d07716f 96
3a935dfa 97(defbinding type-class-ref (type) pointer
98 ((find-type-number type t) type-number))
0d07716f 99
08cb5756 100(defbinding type-class-unref () nil
101 (class pointer))
fc47a022 102
3a935dfa 103(defbinding type-class-peek (type) pointer
104 ((find-type-number type t) type-number))
fc47a022 105
0d07716f 106
08cb5756 107
3a935dfa 108;;;; Mapping between lisp types and glib types
0d07716f 109
dcb31db6 110(defvar *registered-types* ())
111(defvar *registered-type-aliases* ())
0f68f696 112(defvar *registered-static-types* ())
dcb31db6 113(defvar *lisp-type-to-type-number* (make-hash-table))
114(defvar *type-number-to-lisp-type* (make-hash-table))
3a935dfa 115
116(defbinding %type-from-name () type-number
117 (name string))
118
dcb31db6 119(defun type-number-from-glib-name (name &optional (error-p t))
120 (let ((type-number (%type-from-name name)))
121 (cond
122 ((not (zerop type-number)) type-number)
123 (error-p (error "Invalid gtype name: ~A" name)))))
124
b29e33dd 125(defun type-from-glib-name (name)
126 (type-from-number (type-number-from-glib-name name) t))
127
dcb31db6 128(defun register-type (type id)
08cb5756 129 (cond
130 ((find-type-number type))
131 ((not id) (warn "Can't register type with no foreign id: ~A" type))
132 (t
133 (pushnew (cons type id) *registered-types* :key #'car)
134 (let ((type-number
135 (typecase id
136 (string (type-number-from-glib-name id))
137 (symbol (funcall id)))))
138 (setf (gethash type *lisp-type-to-type-number*) type-number)
139 (setf (gethash type-number *type-number-to-lisp-type*) type)
140 type-number))))
dcb31db6 141
142(defun register-type-alias (type alias)
143 (pushnew (cons type alias) *registered-type-aliases* :key #'car)
144 (setf
145 (gethash type *lisp-type-to-type-number*)
146 (find-type-number alias t)))
147
148(defun reinitialize-all-types ()
149 (clrhash *lisp-type-to-type-number*)
150 (clrhash *type-number-to-lisp-type*)
151 (type-init) ; initialize the glib type system
152 (mapc #'(lambda (type)
153 (register-type (car type) (cdr type)))
154 *registered-types*)
e9177b70 155 (mapc #'(lambda (type)
08cb5756 156 (apply #'register-new-type type))
b29e33dd 157 (reverse *registered-static-types*))
dcb31db6 158 (mapc #'(lambda (type)
159 (register-type-alias (car type) (cdr type)))
160 *registered-type-aliases*))
161
162(pushnew 'reinitialize-all-types
163 #+cmu *after-save-initializations*
08cb5756 164 #+sbcl *init-hooks*
165 #+clisp custom:*init-hooks*)
dcb31db6 166
167#+cmu
168(pushnew 'system::reinitialize-global-table ; we shouldn't have to do this?
169 *after-save-initializations*)
170
171
172(defun find-type-number (type &optional error-p)
0d07716f 173 (etypecase type
174 (integer type)
dcb31db6 175 (string (type-number-from-glib-name type error-p))
3a935dfa 176 (symbol
dcb31db6 177 (or
178 (gethash type *lisp-type-to-type-number*)
179 (and error-p (error "Type not registered: ~A" type))))
180 (class (find-type-number (class-name type) error-p))))
0d07716f 181
b011356b 182(defun type-from-number (type-number &optional error)
183 (multiple-value-bind (type found)
dcb31db6 184 (gethash type-number *type-number-to-lisp-type*)
e40a19fb 185 (if found
186 type
dcb31db6 187 (let ((name (find-foreign-type-name type-number)))
e40a19fb 188 (cond
f53fad52 189 ((and name (not (= (type-number-from-glib-name name nil) type-number)))
e40a19fb 190 ;; This is a hack because GdkEvent seems to be registered
191 ;; multiple times
192 (type-from-number (type-number-from-glib-name name)))
193 ((and error name)
194 (error "Type number not registered: ~A (~A)" type-number name))
195 ((and error)
196 (error "Invalid type number: ~A" type-number)))))))
0d07716f 197
dcb31db6 198(defbinding (find-foreign-type-name "g_type_name") (type) (copy-of string)
3a935dfa 199 ((find-type-number type t) type-number))
200
201(defun type-number-of (object)
202 (find-type-number (type-of object) t))
203
6556dccd 204(eval-when (:compile-toplevel :load-toplevel :execute)
dcb31db6 205 (defvar *type-initializers* ())
206 (defun %find-types-in-library (pathname prefixes ignore)
08cb5756 207 (let ((process
208 (run-program
209 "/usr/bin/nm"
210 #+clisp :arguments
0ab57f12 211 (list #-darwin"--defined-only" #-darwin"-D" "-g" #+darwin"-f"
212 #+darwin"-s" #+darwin"__TEXT" #+darwin"__text"
213 (namestring (truename pathname)))
08cb5756 214 :output :stream :wait nil)))
6556dccd 215 (unwind-protect
216 (loop
0ab57f12 217 as line = (read-line
218 #+(or cmu sbcl) (process-output process)
219 #+clisp process
220 nil)
221 as symbol = (when line
222 (let ((pos (position #\Space line :from-end t)))
223 #-darwin(subseq line (1+ pos))
52632d24 224 #+darwin
0ab57f12 225 (when (char= (char line (1- pos)) #\T)
226 (subseq line (+ pos 2)))))
227 while line
6556dccd 228 when (and
0ab57f12 229 symbol (> (length symbol) 9)
7d04d907 230 (not (char= (char symbol 0) #\_))
dcb31db6 231 (or
232 (not prefixes)
233 (some #'(lambda (prefix)
234 (and
235 (> (length symbol) (length prefix))
236 (string= prefix symbol :end2 (length prefix))))
237 (mklist prefixes)))
238 (string= "_get_type" symbol :start2 (- (length symbol) 9))
6556dccd 239 (not (member symbol ignore :test #'string=)))
240 collect symbol)
08cb5756 241 (#+(or cmu sbcl)process-close
242 #+clisp close
243 process)))))
6556dccd 244
0d07716f 245
80031aba 246(defmacro init-types-in-library (filename &key prefix ignore)
6556dccd 247 (let ((names (%find-types-in-library filename prefix ignore)))
248 `(progn
249 ,@(mapcar #'(lambda (name)
250 `(progn
251 (defbinding (,(intern name) ,name) () type-number)
dcb31db6 252 (,(intern name))
253 (pushnew ',(intern name) *type-initializers*)))
6556dccd 254 names))))
255
dcb31db6 256(defun find-type-init-function (type-number)
80031aba 257 (loop
258 for type-init in *type-initializers*
259 when (= type-number (funcall type-init))
260 do (return type-init)))
261
262(defun register-type-as (type-number)
263 (or
264 (find-type-init-function type-number)
265 (find-foreign-type-name type-number)
266 (error "Unknown type-number: ~A" type-number)))
dcb31db6 267
268(defun default-type-init-name (type)
269 (find-symbol (format nil "~A_~A_get_type"
270 (package-prefix *package*)
271 (substitute #\_ #\- (string-downcase type)))))
272
6556dccd 273
0a77b51f 274(eval-when (:compile-toplevel :load-toplevel :execute)
275 (defclass type-info (struct)
276 ((class-size :allocation :alien :type (unsigned 16) :initarg :class-size)
277 (base-init :allocation :alien :type pointer)
278 (base-finalize :allocation :alien :type pointer)
279 (class-init :allocation :alien :type pointer)
280 (class-finalize :allocation :alien :type pointer)
281 (class-data :allocation :alien :type pointer)
282 (instance-size :allocation :alien :type (unsigned 16)
283 :initarg :instance-size)
284 (n-preallocs :allocation :alien :type (unsigned 16))
285 (instance-init :allocation :alien :type pointer)
286 (value-table :allocation :alien :type pointer))
287 (:metaclass struct-class)))
288
289(defbinding %type-register-static () type-number
e40a19fb 290 (parent-type type-number)
0a77b51f 291 (name string)
292 (info type-info)
293 (0 unsigned-int))
294
8fbfa684 295(defun register-new-type (type parent &optional foreign-name)
0a77b51f 296 (let ((parent-info (type-query parent)))
297 (with-slots ((parent-number type-number) class-size instance-size) parent-info
298 (let ((type-number
299 (%type-register-static
300 parent-number
8fbfa684 301 (or foreign-name (default-alien-type-name type))
0a77b51f 302 (make-instance 'type-info :class-size class-size :instance-size instance-size))))
0f68f696 303 (pushnew (list type parent foreign-name) *registered-static-types* :key #'car)
304 (setf (gethash type *lisp-type-to-type-number*) type-number)
305 (setf (gethash type-number *type-number-to-lisp-type*) type)
306 type-number))))
0a77b51f 307
308
6556dccd 309
310;;;; Metaclass for subclasses of ginstance
311
312(eval-when (:compile-toplevel :load-toplevel :execute)
313 (defclass ginstance-class (proxy-class)
7bab08b9 314 ((gtype :initarg :gtype :initform nil :reader ginstance-class-gtype))))
f53fad52 315
316
d905d6ef 317(defun update-size (class)
318 (let ((type-number (find-type-number class)))
319 (cond
08cb5756 320 ((not (foreign-size-p class))
321 (setf (foreign-size class) (type-instance-size type-number)))
d905d6ef 322 ((and
08cb5756 323 (foreign-size-p class)
324 (not (= (type-instance-size type-number) (foreign-size class))))
d905d6ef 325 (warn "Size mismatch for class ~A" class)))))
326
7ce0497d 327
f53fad52 328(defmethod finalize-inheritance ((class ginstance-class))
08cb5756 329 (prog1
330 #+clisp(call-next-method)
331 (let* ((class-name (class-name class))
332 (super (most-specific-proxy-superclass class))
333 (gtype (or
334 (first (ginstance-class-gtype class))
335 (default-alien-type-name class-name)))
336 (type-number
337 (or
338 (find-type-number class-name)
339 (let ((type-number
340 (if (or
341 (symbolp gtype)
342 (type-number-from-glib-name gtype nil))
343 (register-type class-name gtype)
344 (register-new-type class-name (class-name super) gtype))))
345 (type-class-ref type-number)
346 type-number))))
6b716036 347 #+nil
08cb5756 348 (when (and
349 (supertype type-number)
350 (not (eq (class-name super) (supertype type-number))))
351 (warn "Super class mismatch between CLOS and GObject for ~A"
352 class-name)))
353 (update-size class))
354 #-clisp(call-next-method))
d905d6ef 355
356
357(defmethod shared-initialize ((class ginstance-class) names &rest initargs)
08cb5756 358 (declare (ignore names initargs))
d905d6ef 359 (call-next-method)
360 (when (class-finalized-p class)
361 (update-size class)))
362
b011356b 363
6556dccd 364(defmethod validate-superclass ((class ginstance-class) (super standard-class))
365 (subtypep (class-name super) 'ginstance))
366
0d07716f 367
fc47a022 368;;;; Superclass for wrapping types in the glib type system
0d07716f 369
370(eval-when (:compile-toplevel :load-toplevel :execute)
8ac82923 371 (defclass ginstance (ref-counted-object)
7ce0497d 372 (;(class :allocation :alien :type pointer :offset 0)
373 )
374 (:metaclass proxy-class)
375 (:size #.(size-of 'pointer))))
0d07716f 376
08cb5756 377(defun ref-type-number (location &optional offset)
378 (declare (ignore location offset)))
379
380(setf (symbol-function 'ref-type-number) (reader-function 'type-number))
381
609ba905 382(defun %type-number-of-ginstance (location)
08cb5756 383 (let ((class (ref-pointer location)))
384 (ref-type-number class)))
0d07716f 385
08cb5756 386(defmethod make-proxy-instance :around ((class ginstance-class) location
387 &rest initargs)
4d1d3921 388 (declare (ignore class))
609ba905 389 (let ((class (labels ((find-known-class (type-number)
390 (or
391 (find-class (type-from-number type-number) nil)
392 (unless (zerop type-number)
393 (find-known-class (type-parent type-number))))))
394 (find-known-class (%type-number-of-ginstance location)))))
08cb5756 395 ;; Note that chancing the class argument should not alter "the
1d06a422 396 ;; ordered set of applicable methods" as specified in the
397 ;; Hyperspec
4d1d3921 398 (if class
1d06a422 399 (apply #'call-next-method class location initargs)
400 (error "Object at ~A has an unkown type number: ~A"
401 location (%type-number-of-ginstance location)))))
402
0d07716f 403
3a935dfa 404;;;; Registering fundamental types
405
40c346ec 406(register-type 'nil "void")
3a935dfa 407(register-type 'pointer "gpointer")
408(register-type 'char "gchar")
409(register-type 'unsigned-char "guchar")
410(register-type 'boolean "gboolean")
3a935dfa 411(register-type 'int "gint")
0b392a0d 412(register-type-alias 'integer 'int)
dcb31db6 413(register-type-alias 'fixnum 'int)
3a935dfa 414(register-type 'unsigned-int "guint")
415(register-type 'long "glong")
416(register-type 'unsigned-long "gulong")
417(register-type 'single-float "gfloat")
418(register-type 'double-float "gdouble")
b77fe850 419(register-type 'pathname "gchararray")
b011356b 420(register-type 'string "gchararray")
3a935dfa 421
422
e9934f39 423;;;; Introspection of type information
3a935dfa 424
4812615b 425(defvar *derivable-type-info* (make-hash-table))
3a935dfa 426
e9934f39 427(defun register-derivable-type (type id expander &optional dependencies)
3a935dfa 428 (register-type type id)
4812615b 429 (let ((type-number (register-type type id)))
e9934f39 430 (setf
431 (gethash type-number *derivable-type-info*)
432 (list expander dependencies))))
3a935dfa 433
b011356b 434(defun find-type-info (type)
435 (dolist (super (cdr (type-hierarchy type)))
4812615b 436 (let ((info (gethash super *derivable-type-info*)))
b011356b 437 (return-if info))))
438
e9934f39 439(defun expand-type-definition (type forward-p options)
440 (let ((expander (first (find-type-info type))))
441 (funcall expander (find-type-number type t) forward-p options)))
3a935dfa 442
08cb5756 443
3a935dfa 444(defbinding type-parent (type) type-number
445 ((find-type-number type t) type-number))
446
447(defun supertype (type)
448 (type-from-number (type-parent type)))
449
7858d45e 450(defbinding %type-interfaces (type) pointer
451 ((find-type-number type t) type-number)
452 (n-interfaces unsigned-int :out))
453
454(defun type-interfaces (type)
455 (multiple-value-bind (array length) (%type-interfaces type)
456 (unwind-protect
4d1d3921 457 (map-c-vector 'list #'identity array 'type-number length)
7858d45e 458 (deallocate-memory array))))
459
460(defun implements (type)
461 (mapcar #'type-from-number (type-interfaces type)))
462
3a935dfa 463(defun type-hierarchy (type)
464 (let ((type-number (find-type-number type t)))
465 (unless (= type-number 0)
466 (cons type-number (type-hierarchy (type-parent type-number))))))
467
468(defbinding (type-is-p "g_type_is_a") (type super) boolean
469 ((find-type-number type) type-number)
470 ((find-type-number super) type-number))
471
472(defbinding %type-children () pointer
473 (type-number type-number)
474 (num-children unsigned-int :out))
475
476(defun map-subtypes (function type &optional prefix)
477 (let ((type-number (find-type-number type t)))
478 (multiple-value-bind (array length) (%type-children type-number)
479 (unwind-protect
4d1d3921 480 (map-c-vector
3a935dfa 481 'nil
482 #'(lambda (type-number)
483 (when (or
484 (not prefix)
dcb31db6 485 (string-prefix-p prefix (find-foreign-type-name type-number)))
3a935dfa 486 (funcall function type-number))
487 (map-subtypes function type-number prefix))
488 array 'type-number length)
489 (deallocate-memory array)))))
490
491(defun find-types (prefix)
492 (let ((type-list nil))
4812615b 493 (maphash
494 #'(lambda (type-number expander)
495 (declare (ignore expander))
496 (map-subtypes
497 #'(lambda (type-number)
498 (pushnew type-number type-list))
499 type-number prefix))
500 *derivable-type-info*)
3a935dfa 501 type-list))
502
08cb5756 503(defun find-type-dependencies (type &optional options)
504 (let ((find-dependencies (second (find-type-info type))))
505 (when find-dependencies
506 (remove-duplicates
507 (mapcar #'find-type-number
508 (funcall find-dependencies (find-type-number type t) options))))))
509
510
511;; The argument is a list where each elements is on the form
6b716036 512;; (type . dependencies). This function will not handle indirect
513;; dependencies and types depending on them selve.
08cb5756 514(defun sort-types-topologicaly (unsorted)
515 (flet ((depend-p (type1)
516 (find-if #'(lambda (type2)
517 (and
518 ;; If a type depends a subtype it has to be
519 ;; forward defined
520 (not (type-is-p (car type2) (car type1)))
521 (find (car type2) (cdr type1))))
522 unsorted)))
523 (let ((sorted
524 (loop
525 while unsorted
526 nconc (multiple-value-bind (sorted remaining)
527 (delete-collect-if
528 #'(lambda (type)
529 (or (not (cdr type)) (not (depend-p type))))
530 unsorted)
531 (cond
532 ((not sorted)
533 ;; We have a circular dependency which have to
534 ;; be resolved
535 (let ((selected
536 (find-if
537 #'(lambda (type)
538 (every
539 #'(lambda (dep)
540 (or
541 (not (type-is-p (car type) dep))
542 (not (find dep unsorted :key #'car))))
543 (cdr type)))
544 unsorted)))
545 (unless selected
546 (error "Couldn't resolve circular dependency"))
547 (setq unsorted (delete selected unsorted))
548 (list selected)))
549 (t
550 (setq unsorted remaining)
551 sorted))))))
552
553 ;; Mark types which have to be forward defined
554 (loop
555 for tmp on sorted
556 as (type . dependencies) = (first tmp)
557 collect (cons type (and
558 dependencies
559 (find-if #'(lambda (type)
560 (find (car type) dependencies))
561 (rest tmp))
562 t))))))
3a935dfa 563
564
565(defun expand-type-definitions (prefix &optional args)
dcb31db6 566 (flet ((type-options (type-number)
567 (let ((name (find-foreign-type-name type-number)))
b011356b 568 (cdr (assoc name args :test #'string=)))))
3a935dfa 569
4812615b 570 (let ((type-list
571 (delete-if
572 #'(lambda (type-number)
dcb31db6 573 (let ((name (find-foreign-type-name type-number)))
4812615b 574 (or
575 (getf (type-options type-number) :ignore)
576 (find-if
577 #'(lambda (options)
578 (and
579 (string-prefix-p (first options) name)
17c607d0 580 (getf (cdr options) :ignore-prefix)
581 (not (some
582 #'(lambda (exception)
583 (string= name exception))
584 (getf (cdr options) :except)))))
4812615b 585 args))))
586 (find-types prefix))))
6556dccd 587
4812615b 588 (dolist (type-number type-list)
dcb31db6 589 (let ((name (find-foreign-type-name type-number)))
4812615b 590 (register-type
591 (getf (type-options type-number) :type (default-type-name name))
80031aba 592 (register-type-as type-number))))
6556dccd 593
08cb5756 594 ;; This is needed for some unknown reason to get type numbers right
595 (mapc #'find-type-dependencies type-list)
596
597 (let ((sorted-type-list
598 #+clisp (mapcar #'list type-list)
599 #-clisp
600 (sort-types-topologicaly
601 (mapcar
602 #'(lambda (type)
603 (cons type (find-type-dependencies type (type-options type))))
604 type-list))))
e9934f39 605 `(progn
606 ,@(mapcar
6556dccd 607 #'(lambda (pair)
608 (destructuring-bind (type . forward-p) pair
609 (expand-type-definition type forward-p (type-options type))))
610 sorted-type-list)
e9934f39 611 ,@(mapcar
6556dccd 612 #'(lambda (pair)
613 (destructuring-bind (type . forward-p) pair
614 (when forward-p
615 (expand-type-definition type nil (type-options type)))))
e9934f39 616 sorted-type-list))))))
4812615b 617
3a935dfa 618(defmacro define-types-by-introspection (prefix &rest args)
b011356b 619 (expand-type-definitions prefix args))
6556dccd 620
08cb5756 621(defexport define-types-by-introspection (prefix &rest args)
d92bb6e7 622 (list-autoexported-symbols (expand-type-definitions prefix args)))
08cb5756 623
6556dccd 624
625;;;; Initialize all non static types in GObject
626
4b634902 627(init-types-in-library #.(concatenate 'string (pkg-config:pkg-variable "glib-2.0" "libdir") "/libgobject-2.0." asdf:*dso-extension*))