1 (in-package :gobject.ffi
)
3 (defctype g-type gsize
)
5 (defstruct gtype name %id
)
7 (defvar *name-to-gtype
* (make-hash-table :test
'equal
))
8 (defvar *id-to-gtype
* (make-hash-table))
9 (defvar *gtype-lock
* (bt:make-lock
"gtype lock"))
11 (defun invalidate-gtypes ()
12 (bt:with-lock-held
(*gtype-lock
*)
13 (clrhash *id-to-gtype
*)
14 (iter (for (name gtype
) in-hashtable
*name-to-gtype
*)
15 (setf (gtype-%id gtype
) nil
))))
17 (at-finalize () (invalidate-gtypes))
19 (defcfun (%g-type-from-name
"g_type_from_name") g-type
22 (defcfun (%g-type-name
"g_type_name") (:string
:free-from-foreign nil
)
25 (defun warn-unknown-gtype (name)
26 (warn "GType ~A is not known to GObject" name
))
28 (defun gtype-from-name (name)
29 (declare (optimize (safety 0) (speed 3)))
30 (when (null name
) (return-from gtype-from-name nil
))
31 (bt:with-lock-held
(*gtype-lock
*)
32 (let ((type (gethash name
*name-to-gtype
*)))
34 (when (null (gtype-%id type
))
35 (let ((n (%g-type-from-name name
)))
37 (warn-unknown-gtype name
)
39 (setf (gtype-%id type
) n
40 (gethash n
*id-to-gtype
*) type
)))))
41 (return-from gtype-from-name type
)))
42 (let ((n (%g-type-from-name name
)))
44 (warn-unknown-gtype name
)
46 (let ((type (make-gtype :name
(copy-seq name
) :%id n
)))
47 (setf (gethash n
*id-to-gtype
*) type
48 (gethash name
*name-to-gtype
*) type
)
49 (return-from gtype-from-name type
)))))
51 (defun gtype-from-id (id)
52 (declare (optimize (safety 0) (speed 3)))
53 (when (zerop id
) (return-from gtype-from-id nil
))
54 (bt:with-lock-held
(*gtype-lock
*)
55 (let ((type (gethash id
*id-to-gtype
*)))
57 (return-from gtype-from-id type
)))
58 (let ((name (%g-type-name id
)))
60 (warn-unknown-gtype id
))
61 (let ((type (gethash name
*name-to-gtype
*)))
63 (setf (gtype-%id type
) id
64 (gethash id
*id-to-gtype
*) type
)
65 (return-from gtype-from-id type
))
66 (let ((type (make-gtype :name name
:%id id
)))
67 (setf (gethash id
*id-to-gtype
*) type
68 (gethash name
*name-to-gtype
*) type
)
69 (return-from gtype-from-id type
))))))
71 (defun gtype-id (gtype)
72 (when (null gtype
) (return-from gtype-id
0))
73 (when (gtype-%id gtype
) (return-from gtype-id
(gtype-%id gtype
)))
74 (bt:with-lock-held
(*gtype-lock
*)
75 (let ((n (%g-type-from-name
(gtype-name gtype
))))
77 (warn-unknown-gtype (gtype-name gtype
))
78 (return-from gtype-id
0))
79 (setf (gtype-%id gtype
) n
80 (gethash n
*id-to-gtype
*) gtype
)
87 (string (gtype-from-name thing
))
88 (integer (gtype-from-id thing
))))
93 (define-compiler-macro gtype
(&whole whole thing
)
95 `(load-time-value (%gtype
,thing
))
98 (define-foreign-type g-type-designator
()
99 ((mangled-p :initarg
:mangled-p
100 :reader g-type-designator-mangled-p
102 :documentation
"Whether the type designator is mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag"))
103 (:documentation
"Values of this CFFI foreign type identify the GType. GType is designated by a its name (a string) or a numeric identifier. Functions accept GType designators as a string or integer and return them as a string. Functions @fun{g-type-name} and @fun{g-type-from-name} are used to convert between name and numeric identifier.
105 Numeric identifier of GType may be different between different program runs. But string identifier of GType does not change.")
106 (:actual-type g-type
)
107 (:simple-parser g-type-designator
))
109 (defun unmangle-g-type (g-type)
110 (logxor g-type
(ldb (byte 1 0) g-type
)));;subtract the G_SIGNAL_TYPE_STATIC_SCOPE
112 (defmethod translate-from-foreign (value (type g-type-designator
))
113 (gtype (if (g-type-designator-mangled-p type
)
114 (unmangle-g-type value
)
117 (defmethod translate-to-foreign (value (type g-type-designator
))
118 (gtype-id (gtype value
)))
120 (defun g-type= (type-1 type-2
)
121 (eq (gtype type-1
) (gtype type-2
)))
123 (defun g-type/= (type-1 type-2
)
124 (not (eq (gtype type-1
) (gtype type-2
))))