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