chiark / gitweb /
Error message clarified
[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
cf5bbb0e 23;; $Id: gtype.lisp,v 1.63 2007/06/18 13:01:06 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
08eab1a3 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)))
0d07716f 37
b4a2c852 38(deftype gtype () 'symbol)
39
4d1fea77 40(define-type-method alien-type ((type gtype))
41 (declare (ignore type))
b4a2c852 42 (alien-type 'type-number))
43
08cb5756 44(define-type-method size-of ((type gtype) &key (inlined t))
45 (assert-inlined type inlined)
b4a2c852 46 (size-of 'type-number))
47
08cb5756 48(define-type-method to-alien-form ((type gtype) gtype &optional copy-p)
49 (declare (ignore type copy-p))
b4a2c852 50 `(find-type-number ,gtype t))
51
08cb5756 52(define-type-method to-alien-function ((type gtype) &optional copy-p)
53 (declare (ignore type copy-p))
b4a2c852 54 #'(lambda (gtype)
55 (find-type-number gtype t)))
56
08cb5756 57(define-type-method from-alien-form ((type gtype) form &key ref)
58 (declare (ignore type ref))
59 `(type-from-number ,form))
b4a2c852 60
08cb5756 61(define-type-method from-alien-function ((type gtype) &key ref)
62 (declare (ignore type ref))
b4a2c852 63 #'(lambda (type-number)
40c346ec 64 (type-from-number type-number)))
b4a2c852 65
08cb5756 66(define-type-method writer-function ((type gtype) &key temp (inlined t))
67 (declare (ignore temp))
68 (assert-inlined type inlined)
b4a2c852 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
08cb5756 73(define-type-method reader-function ((type gtype) &key ref (inlined t))
74 (declare (ignore ref))
75 (assert-inlined type inlined)
b4a2c852 76 (let ((reader (reader-function 'type-number)))
08cb5756 77 #'(lambda (location &optional (offset 0))
40c346ec 78 (type-from-number (funcall reader location offset)))))
b4a2c852 79
80
fc47a022 81(eval-when (:compile-toplevel :load-toplevel :execute)
3a935dfa 82 (defclass type-query (struct)
fc47a022 83 ((type-number :allocation :alien :type type-number)
08cb5756 84 (name :allocation :alien :type (copy-of string))
fc47a022 85 (class-size :allocation :alien :type unsigned-int)
86 (instance-size :allocation :alien :type unsigned-int))
4d1d3921 87 (:metaclass struct-class)))
fc47a022 88
89
b4a2c852 90(defbinding type-query (type) nil
91 ((find-type-number type t) type-number)
08cb5756 92 ((make-instance 'type-query) type-query :in/return))
fc47a022 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))
0d07716f 99
3a935dfa 100(defbinding type-class-ref (type) pointer
101 ((find-type-number type t) type-number))
0d07716f 102
08cb5756 103(defbinding type-class-unref () nil
104 (class pointer))
fc47a022 105
3a935dfa 106(defbinding type-class-peek (type) pointer
107 ((find-type-number type t) type-number))
fc47a022 108
0d07716f 109
08cb5756 110
3a935dfa 111;;;; Mapping between lisp types and glib types
0d07716f 112
dcb31db6 113(defvar *registered-types* ())
114(defvar *registered-type-aliases* ())
0f68f696 115(defvar *registered-static-types* ())
dcb31db6 116(defvar *lisp-type-to-type-number* (make-hash-table))
117(defvar *type-number-to-lisp-type* (make-hash-table))
3a935dfa 118
119(defbinding %type-from-name () type-number
120 (name string))
121
dcb31db6 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
b29e33dd 128(defun type-from-glib-name (name)
129 (type-from-number (type-number-from-glib-name name) t))
130
dcb31db6 131(defun register-type (type id)
08cb5756 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))))
dcb31db6 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*)
e9177b70 158 (mapc #'(lambda (type)
08cb5756 159 (apply #'register-new-type type))
b29e33dd 160 (reverse *registered-static-types*))
dcb31db6 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*
08cb5756 167 #+sbcl *init-hooks*
168 #+clisp custom:*init-hooks*)
dcb31db6 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)
0d07716f 176 (etypecase type
177 (integer type)
dcb31db6 178 (string (type-number-from-glib-name type error-p))
3a935dfa 179 (symbol
dcb31db6 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))))
0d07716f 184
b011356b 185(defun type-from-number (type-number &optional error)
186 (multiple-value-bind (type found)
dcb31db6 187 (gethash type-number *type-number-to-lisp-type*)
e40a19fb 188 (if found
189 type
dcb31db6 190 (let ((name (find-foreign-type-name type-number)))
e40a19fb 191 (cond
f53fad52 192 ((and name (not (= (type-number-from-glib-name name nil) type-number)))
e40a19fb 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)))))))
0d07716f 200
dcb31db6 201(defbinding (find-foreign-type-name "g_type_name") (type) (copy-of string)
3a935dfa 202 ((find-type-number type t) type-number))
203
204(defun type-number-of (object)
205 (find-type-number (type-of object) t))
206
cf5bbb0e 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
6556dccd 215(eval-when (:compile-toplevel :load-toplevel :execute)
dcb31db6 216 (defvar *type-initializers* ())
217 (defun %find-types-in-library (pathname prefixes ignore)
cf5bbb0e 218 (let ((outname (tmpname "types")))
6556dccd 219 (unwind-protect
cf5bbb0e 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)))))
6556dccd 263
0d07716f 264
07dafdb0 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)))
6556dccd 268 `(progn
269 ,@(mapcar #'(lambda (name)
270 `(progn
271 (defbinding (,(intern name) ,name) () type-number)
dcb31db6 272 (,(intern name))
273 (pushnew ',(intern name) *type-initializers*)))
6556dccd 274 names))))
275
dcb31db6 276(defun find-type-init-function (type-number)
80031aba 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)))
dcb31db6 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
6556dccd 293
0a77b51f 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
e40a19fb 310 (parent-type type-number)
0a77b51f 311 (name string)
312 (info type-info)
313 (0 unsigned-int))
314
8fbfa684 315(defun register-new-type (type parent &optional foreign-name)
0a77b51f 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
8fbfa684 321 (or foreign-name (default-alien-type-name type))
0a77b51f 322 (make-instance 'type-info :class-size class-size :instance-size instance-size))))
0f68f696 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))))
0a77b51f 327
328
6556dccd 329
330;;;; Metaclass for subclasses of ginstance
331
332(eval-when (:compile-toplevel :load-toplevel :execute)
333 (defclass ginstance-class (proxy-class)
7bab08b9 334 ((gtype :initarg :gtype :initform nil :reader ginstance-class-gtype))))
f53fad52 335
336
d905d6ef 337(defun update-size (class)
338 (let ((type-number (find-type-number class)))
339 (cond
08cb5756 340 ((not (foreign-size-p class))
341 (setf (foreign-size class) (type-instance-size type-number)))
d905d6ef 342 ((and
08cb5756 343 (foreign-size-p class)
344 (not (= (type-instance-size type-number) (foreign-size class))))
d905d6ef 345 (warn "Size mismatch for class ~A" class)))))
346
7ce0497d 347
f53fad52 348(defmethod finalize-inheritance ((class ginstance-class))
08cb5756 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))))
6b716036 367 #+nil
08cb5756 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))
d905d6ef 375
376
377(defmethod shared-initialize ((class ginstance-class) names &rest initargs)
08cb5756 378 (declare (ignore names initargs))
d905d6ef 379 (call-next-method)
380 (when (class-finalized-p class)
381 (update-size class)))
382
b011356b 383
6556dccd 384(defmethod validate-superclass ((class ginstance-class) (super standard-class))
385 (subtypep (class-name super) 'ginstance))
386
0d07716f 387
fc47a022 388;;;; Superclass for wrapping types in the glib type system
0d07716f 389
390(eval-when (:compile-toplevel :load-toplevel :execute)
8ac82923 391 (defclass ginstance (ref-counted-object)
7ce0497d 392 (;(class :allocation :alien :type pointer :offset 0)
393 )
394 (:metaclass proxy-class)
395 (:size #.(size-of 'pointer))))
0d07716f 396
08cb5756 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
609ba905 402(defun %type-number-of-ginstance (location)
08cb5756 403 (let ((class (ref-pointer location)))
404 (ref-type-number class)))
0d07716f 405
08cb5756 406(defmethod make-proxy-instance :around ((class ginstance-class) location
407 &rest initargs)
4d1d3921 408 (declare (ignore class))
609ba905 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)))))
08cb5756 415 ;; Note that chancing the class argument should not alter "the
1d06a422 416 ;; ordered set of applicable methods" as specified in the
417 ;; Hyperspec
4d1d3921 418 (if class
1d06a422 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
0d07716f 423
3a935dfa 424;;;; Registering fundamental types
425
40c346ec 426(register-type 'nil "void")
3a935dfa 427(register-type 'pointer "gpointer")
428(register-type 'char "gchar")
429(register-type 'unsigned-char "guchar")
430(register-type 'boolean "gboolean")
3a935dfa 431(register-type 'int "gint")
0b392a0d 432(register-type-alias 'integer 'int)
dcb31db6 433(register-type-alias 'fixnum 'int)
3a935dfa 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")
b77fe850 439(register-type 'pathname "gchararray")
b011356b 440(register-type 'string "gchararray")
3a935dfa 441
442
e9934f39 443;;;; Introspection of type information
3a935dfa 444
4812615b 445(defvar *derivable-type-info* (make-hash-table))
3a935dfa 446
e9934f39 447(defun register-derivable-type (type id expander &optional dependencies)
3a935dfa 448 (register-type type id)
4812615b 449 (let ((type-number (register-type type id)))
e9934f39 450 (setf
451 (gethash type-number *derivable-type-info*)
452 (list expander dependencies))))
3a935dfa 453
b011356b 454(defun find-type-info (type)
455 (dolist (super (cdr (type-hierarchy type)))
4812615b 456 (let ((info (gethash super *derivable-type-info*)))
b011356b 457 (return-if info))))
458
e9934f39 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)))
3a935dfa 462
08cb5756 463
3a935dfa 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
7858d45e 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
4d1d3921 477 (map-c-vector 'list #'identity array 'type-number length)
7858d45e 478 (deallocate-memory array))))
479
480(defun implements (type)
481 (mapcar #'type-from-number (type-interfaces type)))
482
3a935dfa 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
4d1d3921 500 (map-c-vector
3a935dfa 501 'nil
502 #'(lambda (type-number)
503 (when (or
504 (not prefix)
dcb31db6 505 (string-prefix-p prefix (find-foreign-type-name type-number)))
3a935dfa 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))
4812615b 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*)
3a935dfa 521 type-list))
522
08cb5756 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
6b716036 532;; (type . dependencies). This function will not handle indirect
07dafdb0 533;; dependencies and types depending on them selves.
08cb5756 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))))))
3a935dfa 583
584
585(defun expand-type-definitions (prefix &optional args)
dcb31db6 586 (flet ((type-options (type-number)
587 (let ((name (find-foreign-type-name type-number)))
b011356b 588 (cdr (assoc name args :test #'string=)))))
3a935dfa 589
4812615b 590 (let ((type-list
591 (delete-if
592 #'(lambda (type-number)
dcb31db6 593 (let ((name (find-foreign-type-name type-number)))
4812615b 594 (or
595 (getf (type-options type-number) :ignore)
596 (find-if
597 #'(lambda (options)
598 (and
599 (string-prefix-p (first options) name)
17c607d0 600 (getf (cdr options) :ignore-prefix)
601 (not (some
602 #'(lambda (exception)
603 (string= name exception))
604 (getf (cdr options) :except)))))
4812615b 605 args))))
606 (find-types prefix))))
6556dccd 607
4812615b 608 (dolist (type-number type-list)
dcb31db6 609 (let ((name (find-foreign-type-name type-number)))
4812615b 610 (register-type
611 (getf (type-options type-number) :type (default-type-name name))
80031aba 612 (register-type-as type-number))))
6556dccd 613
08cb5756 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))))
e9934f39 625 `(progn
626 ,@(mapcar
6556dccd 627 #'(lambda (pair)
628 (destructuring-bind (type . forward-p) pair
629 (expand-type-definition type forward-p (type-options type))))
630 sorted-type-list)
e9934f39 631 ,@(mapcar
6556dccd 632 #'(lambda (pair)
633 (destructuring-bind (type . forward-p) pair
634 (when forward-p
635 (expand-type-definition type nil (type-options type)))))
e9934f39 636 sorted-type-list))))))
4812615b 637
3a935dfa 638(defmacro define-types-by-introspection (prefix &rest args)
b011356b 639 (expand-type-definitions prefix args))
6556dccd 640
08cb5756 641(defexport define-types-by-introspection (prefix &rest args)
d92bb6e7 642 (list-autoexported-symbols (expand-type-definitions prefix args)))
08cb5756 643
6556dccd 644
645;;;; Initialize all non static types in GObject
646
07dafdb0 647(init-types-in-library glib "libgobject-2.0")