Re-registering custom signals and class closures when loading saved images
[clg] / glib / gcallback.lisp
CommitLineData
55212af1 1;; Common Lisp bindings for GTK+ v2.x
2;; Copyright 2000 Espen S. Johnsen <espen@users.sf.net>
c9819f3e 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:
c9819f3e 11;;
55212af1 12;; The above copyright notice and this permission notice shall be
13;; included in all copies or substantial portions of the Software.
c9819f3e 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
ccd6ea40 23;; $Id: gcallback.lisp,v 1.51 2009/02/10 15:18:15 espen Exp $
c9819f3e 24
25(in-package "GLIB")
26
27(use-prefix "g")
28
29
40d51d98 30;;;; Callback invocation
c9819f3e 31
f7573853 32(deftype gclosure () 'pointer)
33(register-type 'gclosure '|g_closure_get_type|)
34
60cfb912 35(defun register-callback-function (function)
36 (check-type function (or null symbol function))
37 (register-user-data function))
c9819f3e 38
15b86b1e 39(deftype user-callback () '(or function symbol))
40
41(define-type-method alien-type ((type user-callback))
42 (declare (ignore type))
43 (alien-type 'pointer-data))
44
45(define-type-method to-alien-form ((type user-callback) func &optional copy-p)
46 (declare (ignore type copy-p))
47 `(register-callback-function ,func))
48
49
26109728 50;; Callback marshaller for regular signal handlers
51(define-callback signal-handler-marshal nil
a92553bd 52 ((gclosure gclosure) (return-value gvalue) (n-params unsigned-int)
53 (param-values pointer) (invocation-hint pointer)
6f937184 54 (callback-id pointer-data))
08d14e5e 55 (declare (ignore gclosure invocation-hint))
26109728 56 (callback-trampoline #'invoke-signal-handler callback-id n-params param-values return-value))
c9819f3e 57
6f937184 58;; Callback marshaller for class handlers
26109728 59(define-callback class-handler-marshal nil
60 ((gclosure gclosure) (return-value gvalue) (n-params unsigned-int)
61 (param-values pointer) (invocation-hint pointer)
6f937184 62 (callback-id pointer-data))
26109728 63 (declare (ignore gclosure invocation-hint))
64 (callback-trampoline #'invoke-callback callback-id n-params param-values return-value))
65
66;; Callback marshaller for emission hooks
67(define-callback emission-hook-marshal nil
a92553bd 68 ((invocation-hint pointer) (n-params unsigned-int) (param-values pointer)
6f937184 69 (callback-id pointer-data))
f84e7a8e 70 (declare (ignore invocation-hint))
26109728 71 (callback-trampoline #'invoke-callback callback-id n-params param-values))
3b8e5eb0 72
26109728 73(defun callback-trampoline (restart-wrapper callback-id n-params param-values
74 &optional (return-value (make-pointer 0)))
c9819f3e 75 (let* ((return-type (unless (null-pointer-p return-value)
60cfb912 76 (gvalue-type return-value)))
831668e8 77 (args (loop
78 for n from 0 below n-params
ad112f20 79 for offset from 0 by +gvalue-size+
10ede675 80 collect (gvalue-peek (pointer+ param-values offset)))))
ad112f20 81 (unwind-protect
26109728 82 (multiple-value-bind (result aborted-p)
83 (apply restart-wrapper callback-id nil args)
84 (when (and return-type (not aborted-p))
ad112f20 85 (gvalue-set return-value result)))
10ede675 86 ;; TODO: this should be made more general, by adding a type
26109728 87 ;; method to return invalidating functions.
ad112f20 88 (loop
89 for arg in args
10ede675 90 when (typep arg 'struct)
ad112f20 91 do (invalidate-instance arg)))))
92
26109728 93(defun invoke-signal-handler (callback-id return-type &rest args)
94 (declare (ignore return-type))
95 (let* ((instance (first args))
96 (handler-id (signal-handler-find instance '(:data)
97 0 0 nil nil callback-id)))
98 (signal-handler-block instance handler-id)
99 (unwind-protect
100 (restart-case (apply #'invoke-callback callback-id nil args)
4dc69f6a 101 (disconnect () :report "Disconnect and exit signal handler"
26109728 102 (when (signal-handler-is-connected-p instance handler-id)
103 (signal-handler-disconnect instance handler-id))
15b86b1e 104 (values nil t)))
26109728 105 (when (signal-handler-is-connected-p instance handler-id)
15b86b1e 106 (signal-handler-unblock instance handler-id)))))
831668e8 107
7bde5a67 108(defun invoke-callback (callback-id return-type &rest args)
26109728 109 (restart-case (apply (find-user-data callback-id) args)
831668e8 110 (continue nil :report "Return from callback function"
26109728 111 (cond
112 (return-type
113 (format *query-io* "Enter return value of type ~S: " return-type)
114 (force-output *query-io*)
115 (eval (read *query-io*)))
116 (t (values nil t))))
831668e8 117 (re-invoke nil :report "Re-invoke callback function"
26109728 118 (apply #'invoke-callback callback-id return-type args))))
c9819f3e 119
c9819f3e 120
60cfb912 121;;;; Timeouts and idle functions
122
0f2fb864 123(defconstant +priority-high+ -100)
124(defconstant +priority-default+ 0)
125(defconstant +priority-high-idle+ 100)
126(defconstant +priority-default-idle+ 200)
127(defconstant +priority-low+ 300)
128
129(defbinding source-remove () boolean
130 (tag unsigned-int))
131
4dc69f6a 132(define-callback source-callback-marshal boolean ((callback-id unsigned-int))
133 (invoke-source-callback callback-id))
134
fd9bf5a6 135(defun invoke-source-callback (callback-id &rest args)
136 (restart-case (apply (find-user-data callback-id) args)
4dc69f6a 137 (remove () :report "Exit and remove source callback"
138 nil)
139 (continue () :report "Return from source callback"
140 t)
141 (re-invoke nil :report "Re-invoke source callback"
fd9bf5a6 142 (apply #'invoke-source-callback callback-id args))))
4dc69f6a 143
60cfb912 144
145(defbinding (timeout-add "g_timeout_add_full")
0f2fb864 146 (interval function &optional (priority +priority-default+)) unsigned-int
60cfb912 147 (priority int)
148 (interval unsigned-int)
a92553bd 149 (source-callback-marshal callback)
60cfb912 150 ((register-callback-function function) unsigned-long)
a92553bd 151 (user-data-destroy-callback callback))
60cfb912 152
0f2fb864 153(defun timeout-remove (timeout)
154 (source-remove timeout))
155
60cfb912 156(defbinding (idle-add "g_idle_add_full")
0f2fb864 157 (function &optional (priority +priority-default-idle+)) unsigned-int
60cfb912 158 (priority int)
a92553bd 159 (source-callback-marshal callback)
60cfb912 160 ((register-callback-function function) unsigned-long)
a92553bd 161 (user-data-destroy-callback callback))
60cfb912 162
0f2fb864 163(defun idle-remove (idle)
164 (source-remove idle))
60cfb912 165
c9819f3e 166
3b8e5eb0 167;;;; Signal information querying
c9819f3e 168
3b8e5eb0 169(defbinding signal-lookup (name type) unsigned-int
c9819f3e 170 ((signal-name-to-string name) string)
3b8e5eb0 171 ((find-type-number type t) type-number))
c9819f3e 172
cd5a3e28 173(defbinding signal-name () (or null (copy-of string))
c9819f3e 174 (signal-id unsigned-int))
175
3b8e5eb0 176(defbinding signal-list-ids (type) (vector unsigned-int n-ids)
177 ((find-type-number type t) type-number)
178 (n-ids unsigned-int :out))
179
180(defun signal-list-names (type)
181 (map 'list #'signal-name (signal-list-ids type)))
182
183(defun ensure-signal-id-from-type (signal-id type)
c9819f3e 184 (etypecase signal-id
3b8e5eb0 185 (integer (if (signal-name signal-id)
186 signal-id
187 (error "Invalid signal id: ~D" signal-id)))
188 ((or symbol string)
189 (let ((numeric-id (signal-lookup signal-id type)))
190 (if (zerop numeric-id)
191 (error "Invalid signal name for ~S: ~D" type signal-id)
192 numeric-id)))))
193
194(defun ensure-signal-id (signal-id instance)
195 (ensure-signal-id-from-type signal-id (type-of instance)))
c9819f3e 196
3b8e5eb0 197(eval-when (:compile-toplevel :load-toplevel :execute)
198 (deftype signal-flags ()
199 '(flags :run-first :run-last :run-cleanup :no-recurse
200 :detailed :action :no-hooks))
201
26109728 202 (define-flags-type signal-match-type
203 :id :detail :closure :func :data :unblocked)
204
3b8e5eb0 205 (defclass signal-query (struct)
206 ((id :allocation :alien :type unsigned-int)
207 (name :allocation :alien :type (copy-of string))
208 (type :allocation :alien :type type-number)
209 (flags :allocation :alien :type signal-flags)
210 (return-type :allocation :alien :type type-number)
211 (n-params :allocation :alien :type unsigned-int)
212 (param-types :allocation :alien :type pointer))
213 (:metaclass struct-class)))
214
215(defbinding signal-query
216 (signal-id &optional (signal-query (make-instance 'signal-query))) nil
217 (signal-id unsigned-int)
10ede675 218 (signal-query signal-query :in/return))
3b8e5eb0 219
220(defun signal-param-types (info)
221 (with-slots (n-params param-types) info
222 (map-c-vector 'list
223 #'(lambda (type-number)
224 (type-from-number type-number))
225 param-types 'type-number n-params)))
226
227
228(defun describe-signal (signal-id &optional type)
229 (let ((info (signal-query (ensure-signal-id-from-type signal-id type))))
230 (with-slots (id name type flags return-type n-params) info
40d51d98 231 (format t "The signal with id ~D is named '~A' and may be emitted on instances of type ~S." id name (type-from-number type t))
232 (when flags
233 (format t " It has the followin invocation flags: ~{~S ~}" flags))
234 (format t "~%~%Signal handlers should take ~A and return ~A~%"
3b8e5eb0 235 (if (zerop n-params)
236 "no arguments"
237 (format nil "arguments with the following types: ~A"
40d51d98 238 (signal-param-types info)))
239 (cond
240 ((= return-type (find-type-number "void")) "no values")
241 ((not (type-from-number return-type)) "values of unknown type")
242 ((format nil "values of type ~S" (type-from-number return-type))))))))
3b8e5eb0 243
244
245;;;; Signal connecting and controlling
246
9a19788c 247(define-flags-type connect-flags :after :swapped)
248
ccd6ea40 249(defvar *signal-override-closures* (make-hash-table :test 'equalp))
2d3de529 250
ccd6ea40 251(defbinding %%signal-override-class-closure () nil
2d3de529 252 (signal-id unsigned-int)
253 (type-number type-number)
254 (callback-closure pointer))
255
256
ccd6ea40 257(defun %signal-override-class-closure (type name function)
258 (multiple-value-bind (callback-closure callback-id)
259 (make-callback-closure function class-handler-marshal)
260 (let ((signal-id (ensure-signal-id-from-type name type)))
261 (%%signal-override-class-closure signal-id (find-type-number type t) callback-closure))
262 (setf
263 (gethash (list type name) *signal-override-closures*)
264 (list callback-id function))))
265
2d3de529 266(defun signal-override-class-closure (name type function)
ccd6ea40 267 (let ((callback-id
268 (first (gethash (list type name) *signal-override-closures*))))
2d3de529 269 (if callback-id
270 (update-user-data callback-id function)
ccd6ea40 271 (%signal-override-class-closure type name function))))
2d3de529 272
ccd6ea40 273(defun reinitialize-signal-override-class-closures ()
274 (maphash
275 #'(lambda (key value)
276 (destructuring-bind (type name) key
277 (destructuring-bind (callback-id function) value
278 (declare (ignore callback-id))
279 (%signal-override-class-closure type name function))))
280 *signal-override-closures*))
2d3de529 281
282(defbinding %signal-chain-from-overridden () nil
283 (args pointer)
284 (return-value (or null gvalue)))
285
e9151788 286
287(defun %call-next-handler (n-params types args return-type)
2d3de529 288 (let ((params (allocate-memory (* n-params +gvalue-size+))))
289 (loop
e9151788 290 for arg in args
2d3de529 291 for type in types
292 for offset from 0 by +gvalue-size+
10ede675 293 do (gvalue-init (pointer+ params offset) type arg))
2d3de529 294
295 (unwind-protect
296 (if return-type
297 (with-gvalue (return-value return-type)
298 (%signal-chain-from-overridden params return-value))
299 (%signal-chain-from-overridden params nil))
300 (progn
301 (loop
302 repeat n-params
303 for offset from 0 by +gvalue-size+
10ede675 304 do (gvalue-unset (pointer+ params offset)))
2d3de529 305 (deallocate-memory params)))))
306
2d3de529 307(defmacro define-signal-handler (name ((object class) &rest args) &body body)
308 (let* ((info (signal-query (ensure-signal-id-from-type name class)))
309 (types (cons class (signal-param-types info)))
310 (n-params (1+ (slot-value info 'n-params)))
311 (return-type (type-from-number (slot-value info 'return-type)))
312 (vars (loop
313 for arg in args
314 until (eq arg '&rest)
315 collect arg))
316 (rest (cadr (member '&rest args)))
e9151788 317 (next (make-symbol "ARGS"))
318 (default (make-symbol "DEFAULT")))
2d3de529 319
320 `(progn
321 (signal-override-class-closure ',name ',class
322 #'(lambda (,object ,@args)
e9151788 323 (let ((,default (list* ,object ,@vars ,rest)))
324 (flet ((call-next-handler (&rest ,next)
2d3de529 325 (%call-next-handler
2e8019d5 326 ,n-params ',types (or ,next ,default) ',return-type)))
327 ,@body))))
2d3de529 328 ',name)))
329
330
3b8e5eb0 331(defbinding %signal-stop-emission () nil
c9819f3e 332 (instance ginstance)
3b8e5eb0 333 (signal-id unsigned-int)
334 (detail quark))
335
336(defvar *signal-stop-emission* nil)
337(declaim (special *signal-stop-emission*))
c9819f3e 338
3b8e5eb0 339(defun signal-stop-emission ()
340 (if *signal-stop-emission*
341 (funcall *signal-stop-emission*)
342 (error "Not inside a signal handler")))
343
344
345(defbinding signal-add-emission-hook (type signal function &key (detail 0))
26109728 346 unsigned-long
3b8e5eb0 347 ((ensure-signal-id-from-type signal type) unsigned-int)
348 (detail quark)
26109728 349 (emission-hook-marshal callback)
3b8e5eb0 350 ((register-callback-function function) unsigned-int)
a92553bd 351 (user-data-destroy-callback callback))
3b8e5eb0 352
353(defbinding signal-remove-emission-hook (type signal hook-id) nil
354 ((ensure-signal-id-from-type signal type) unsigned-int)
26109728 355 (hook-id unsigned-long))
c9819f3e 356
c9819f3e 357
3f4249c7 358(defbinding (signal-has-handler-pending-p "g_signal_has_handler_pending")
c9819f3e 359 (instance signal-id &key detail blocked) boolean
360 (instance ginstance)
7eec806d 361 ((ensure-signal-id signal-id instance) unsigned-int)
c9819f3e 362 ((or detail 0) quark)
3d36c5d6 363 (blocked boolean))
c9819f3e 364
26109728 365(defbinding %signal-connect-closure-by-id () unsigned-long
c9819f3e 366 (instance ginstance)
3b8e5eb0 367 (signal-id unsigned-int)
368 (detail quark)
369 (closure pointer)
c9819f3e 370 (after boolean))
371
3f4249c7 372(defbinding signal-handler-block () nil
c9819f3e 373 (instance ginstance)
26109728 374 (handler-id unsigned-long))
c9819f3e 375
3f4249c7 376(defbinding signal-handler-unblock () nil
c9819f3e 377 (instance ginstance)
26109728 378 (handler-id unsigned-long))
379
380;; Internal
381(defbinding signal-handler-find () unsigned-long
382 (instance gobject)
383 (mask signal-match-type)
384 (signal-id unsigned-int)
385 (detail quark)
386 (closure (or null pointer))
387 (func (or null pointer))
99d59d2a 388 (data pointer-data))
c9819f3e 389
3f4249c7 390(defbinding signal-handler-disconnect () nil
c9819f3e 391 (instance ginstance)
26109728 392 (handler-id unsigned-long))
3b8e5eb0 393
394(defbinding signal-handler-is-connected-p () boolean
395 (instance ginstance)
26109728 396 (handler-id unsigned-long))
c9819f3e 397
9c7196d0 398(defbinding (closure-new "g_cclosure_new") () gclosure
399 ((make-pointer #xFFFFFFFF) pointer)
3b8e5eb0 400 (callback-id unsigned-int)
a92553bd 401 (destroy-notify callback))
c9819f3e 402
9c7196d0 403(defbinding closure-set-meta-marshal () nil
404 (gclosure gclosure)
405 (callback-id unsigned-int)
406 (callback callback))
407
408(defun callback-closure-new (callback-id callback destroy-notify)
409 (let ((gclosure (closure-new callback-id destroy-notify)))
410 (closure-set-meta-marshal gclosure callback-id callback)
411 gclosure))
412
99d59d2a 413(defun make-callback-closure (function &optional (marshaller signal-handler-marshal))
3b8e5eb0 414 (let ((callback-id (register-callback-function function)))
415 (values
26109728 416 (callback-closure-new callback-id marshaller user-data-destroy-callback)
3b8e5eb0 417 callback-id)))
418
40d51d98 419(defgeneric compute-signal-function (gobject signal function object args))
a6e13fb0 420
40d51d98 421(defmethod compute-signal-function ((gobject gobject) signal function object args)
54ea42fe 422 (declare (ignore signal))
3b8e5eb0 423 (cond
40d51d98 424 ((or (eq object t) (eq object gobject))
425 (if args
426 #'(lambda (&rest emission-args)
427 (apply function (nconc emission-args args)))
428 function))
429 (object
430 (if args
431 #'(lambda (&rest emission-args)
432 (apply function object (nconc (rest emission-args) args)))
433 #'(lambda (&rest emission-args)
434 (apply function object (rest emission-args)))))
435 (args
436 #'(lambda (&rest emission-args)
437 (apply function (nconc (rest emission-args) args))))
3b8e5eb0 438 (t
40d51d98 439 #'(lambda (&rest emission-args)
440 (apply function (rest emission-args))))))
54ea42fe 441
442(defgeneric compute-signal-id (gobject signal))
443
444(defmethod compute-signal-id ((gobject gobject) signal)
445 (ensure-signal-id signal gobject))
446
447
40d51d98 448(defgeneric signal-connect (gobject signal function &key detail after object remove args))
54ea42fe 449
450(defmethod signal-connect :around ((gobject gobject) signal function &rest args)
451 (declare (ignore gobject signal args))
452 (when function
453 (call-next-method)))
3b8e5eb0 454
a6e13fb0 455
3b8e5eb0 456(defmethod signal-connect ((gobject gobject) signal function
40d51d98 457 &key detail after object remove args)
3b8e5eb0 458"Connects a callback function to a signal for a particular object. If
459:OBJECT is T, the object connected to is passed as the first argument
460to the callback function, or if :OBJECT is any other non NIL value, it
461is passed as the first argument instead. If :AFTER is non NIL, the
462handler will be called after the default handler for the signal. If
463:REMOVE is non NIL, the handler will be removed after beeing invoked
40d51d98 464once. ARGS is a list of additional arguments passed to the callback
465function."
bedf7b84 466 (let* ((signal-id (compute-signal-id gobject signal))
467 (detail-quark (if detail (quark-intern detail) 0))
468 (callback
469 (compute-signal-function gobject signal function object args))
470 (wrapper
471 #'(lambda (&rest args)
472 (let ((*signal-stop-emission*
473 #'(lambda ()
474 (%signal-stop-emission (first args)
475 signal-id detail-quark))))
476 (apply callback args)))))
477 (multiple-value-bind (closure-id callback-id)
478 (make-callback-closure wrapper signal-handler-marshal)
479 (let ((handler-id (%signal-connect-closure-by-id
480 gobject signal-id detail-quark closure-id after)))
481 (when remove
482 (update-user-data callback-id
483 #'(lambda (&rest args)
484 (let ((gobject (first args)))
3b8e5eb0 485 (unwind-protect
bedf7b84 486 (let ((*signal-stop-emission*
487 #'(lambda ()
488 (%signal-stop-emission gobject
489 signal-id detail-quark))))
490 (apply callback args))
26109728 491 (when (signal-handler-is-connected-p gobject handler-id)
bedf7b84 492 (signal-handler-disconnect gobject handler-id)))))))
493 handler-id))))
3b8e5eb0 494
495
496;;;; Signal emission
497
498(defbinding %signal-emitv () nil
499 (gvalues pointer)
500 (signal-id unsigned-int)
501 (detail quark)
502 (return-value gvalue))
503
504(defvar *signal-emit-functions* (make-hash-table))
505
506(defun create-signal-emit-function (signal-id)
507 (let ((info (signal-query signal-id)))
508 (let* ((type (type-from-number (slot-value info 'type)))
509 (param-types (cons type (signal-param-types info)))
510 (return-type (type-from-number (slot-value info 'return-type)))
511 (n-params (1+ (slot-value info 'n-params)))
512 (params (allocate-memory (* n-params +gvalue-size+))))
513 #'(lambda (detail object &rest args)
514 (unless (= (length args) (1- n-params))
9752a742 515 (error "Invalid number of arguments in emmision of signal ~A: ~A" signal-id (length args)))
3b8e5eb0 516 (unwind-protect
517 (loop
518 for arg in (cons object args)
519 for type in param-types
10ede675 520 as tmp = params then (pointer+ tmp +gvalue-size+)
3b8e5eb0 521 do (gvalue-init tmp type arg)
522 finally
523 (if return-type
524 (return
6582d0be 525 (with-gvalue (return-value return-type)
3b8e5eb0 526 (%signal-emitv params signal-id detail return-value)))
527 (%signal-emitv params signal-id detail (make-pointer 0))))
528 (loop
529 repeat n-params
10ede675 530 as tmp = params then (pointer+ tmp +gvalue-size+)
3b8e5eb0 531 while (gvalue-p tmp)
532 do (gvalue-unset tmp)))))))
533
534(defun signal-emit-with-detail (object signal detail &rest args)
535 (let* ((signal-id (ensure-signal-id signal object))
536 (function (or
537 (gethash signal-id *signal-emit-functions*)
538 (setf
539 (gethash signal-id *signal-emit-functions*)
540 (create-signal-emit-function signal-id)))))
541 (apply function detail object args)))
542
543(defun signal-emit (object signal &rest args)
544 (apply #'signal-emit-with-detail object signal 0 args))
545
dd181a20 546
40d51d98 547;;;; Signal registration
548
ccd6ea40 549(defvar *registered-signals* ())
550
40d51d98 551(defbinding %signal-newv (name itype flags return-type param-types)
552 unsigned-int
553 ((signal-name-to-string name) string)
554 (itype gtype)
555 (flags signal-flags)
556 (nil null) ; class closure
557 (nil null) ; accumulator
558 (nil null) ; accumulator data
559 (nil null) ; c marshaller
560 (return-type gtype)
561 ((length param-types) unsigned-int)
562 (param-types (vector gtype)))
563
564(defun signal-new (name itype flags return-type param-types)
565 (when (zerop (signal-lookup name itype))
ccd6ea40 566 (push (list name itype flags return-type param-types) *registered-signals*)
40d51d98 567 (%signal-newv name itype flags return-type param-types)))
568
ccd6ea40 569(defun reinitialize-signals ()
570 (mapc #'(lambda (args) (apply #'%signal-newv args)) *registered-signals*))
571
572(asdf:install-init-hook 'reinitialize-signals)
573(asdf:install-init-hook 'reinitialize-signal-override-class-closures)
574
11e1e57c 575;;;; Convenient macros
576
a92553bd 577(defmacro define-callback-marshal (name return-type args &key (callback-id :last))
578 (let* ((ignore ())
579 (params ())
580 (names (loop
581 for arg in args
582 collect (if (or
583 (eq arg :ignore)
584 (and (consp arg) (eq (first arg) :ignore)))
585 (let ((name (gensym "IGNORE")))
586 (push name ignore)
587 name)
588 (let ((name (if (atom arg)
589 (gensym (string arg))
590 (first arg))))
591 (push name params)
592 name))))
593 (types (loop
594 for arg in args
595 collect (cond
596 ((eq arg :ignore) 'pointer)
597 ((atom arg) arg)
598 (t (second arg))))))
599 `(define-callback ,name ,return-type
600 ,(ecase callback-id
865efd45 601 (:first `((callback-id pointer-data) ,@(mapcar #'list names types)))
602 (:last `(,@(mapcar #'list names types) (callback-id pointer-data))))
a92553bd 603 (declare (ignore ,@ignore))
ad3e0b2b 604 (invoke-callback callback-id ',return-type ,@(nreverse params)))))
11e1e57c 605
606(defmacro with-callback-function ((id function) &body body)
607 `(let ((,id (register-callback-function ,function)))
608 (unwind-protect
609 (progn ,@body)
610 (destroy-user-data ,id))))