repos
/
smoke
/ annotate_shade
summary
|
shortlog
|
log
|
tree
|
commit
|
commitdiff
|
headdiff
|
annotate
|
headblob
|
headfilediff
|
filehistory
normal
|
plain
|
shade
|
zebra
Use strcmp, fix constructor & destrucor calling for classes witn namespace (phonon::MediaPlayer) and add :arg0 to :arg2 initargs
Annotate for file src/clos.lisp
2009-04-05 tobias
1
(in-package #:smoke)
15:36:29 '
2
'
3
(declaim (inline lispify))
'
4
(defun lispify (name &optional (package nil))
'
5
"Returns the interned symbol for name in Lisp style."
'
6
(declare (string name)
'
7
(optimize (speed 3)))
'
8
(if (null package)
'
9
(values (intern (cxx-to-lisp name)))
'
10
(values (intern (cxx-to-lisp name) package))))
'
11
2009-08-02 tobias
12
2009-04-05 tobias
13
(defmacro define-string-transform (name documentation &body states)
15:36:29 '
14
"Defines a function to transform a string."
'
15
(let ((output (gensym))
'
16
(index (gensym))
'
17
(length (gensym)))
'
18
`(defun ,name (input)
'
19
,documentation
'
20
(declare (simple-string input)
'
21
(optimize (speed 3)))
2009-07-22 tobias
22
;; At least on sbcl 1.0.25.debian CONCATENATE is faster than
22:26:05 '
23
;; VECTOR-PUSH-EXTEND.
2009-04-05 tobias
24
(let ((,output "")
15:36:29 '
25
(,index 0)
'
26
(,length (length input))
'
27
(char #\Null))
'
28
(declare (base-char char))
'
29
(macrolet ((next-char ()
'
30
`(if (>= ,',index ,',length)
'
31
(return-from transform ,',output)
'
32
(progn
'
33
(setf char (aref input ,',index))
'
34
(incf ,',index))))
'
35
(go-next (tag)
'
36
`(progn (next-char)
'
37
(go ,tag)))
'
38
(append-char (char)
'
39
`(setf ,',output (concatenate 'string
'
40
,',output
'
41
(string ,char)))))
'
42
(block transform
'
43
(tagbody
'
44
(next-char) ;; Get first char
'
45
,@(reduce #'append
'
46
(mapcar #'(lambda (state)
'
47
(if (stringp (second state))
'
48
`(,(first state) . ,(cddr state))
'
49
state))
'
50
states)))))))))
'
51
'
52
'
53
(define-string-transform lisp-to-cxx
'
54
"Converts LISP-STYLE to camelCase.
2009-07-01 tobias
55
Note that (LISP-TO-CXX (CXX-TO-LIST SOME-STRING)) will not necessarily return
10:54:01 '
56
a string equal to SOME-STRING."
2009-04-05 tobias
57
(default
2009-07-01 tobias
58
"Down case, convert _ and dispatch."
2009-04-05 tobias
59
(case char
15:36:29 '
60
(#\- (go-next camel-upcase))
'
61
(#\. (go-next namespace))
'
62
(t (append-char (char-downcase char))
'
63
(go-next default))))
'
64
(camel-upcase
'
65
"Convert camelCase to lisp-style."
'
66
(append-char char)
'
67
(go-next default))
'
68
(namespace
'
69
"Convert . to ::"
'
70
(append-char #\:)
'
71
(append-char #\:)
'
72
(go default)))
'
73
'
74
(define-string-transform cxx-to-lisp
2009-04-17 tobias
75
"Returns camelCase STRING in lisp-style."
2009-04-05 tobias
76
(begin
2009-07-01 tobias
77
"Strip leading Q or K."
2009-04-05 tobias
78
(case char
15:36:29 '
79
(#\K (go-next default))
'
80
(#\Q (go-next default))
'
81
(t (go default))))
'
82
(default
2009-07-01 tobias
83
"Up case, convert _ and dispatch."
2009-04-05 tobias
84
(case char
15:36:29 '
85
(#\: (go-next namespace))
'
86
(#\_ (append-char #\-)
'
87
(go-next default))
2009-04-17 tobias
88
(#\ (append-char #\-) ;; space (cast operators)
15:26:55 '
89
(go-next default))
2009-04-05 tobias
90
(t (append-char (char-upcase char))
15:36:29 '
91
(if (lower-case-p char)
'
92
(go-next camel-case)
'
93
(go-next default)))))
'
94
(namespace
2009-06-22 tobias
95
"C++ namespace separator"
2009-04-05 tobias
96
(assert (eql #\: char))
15:36:29 '
97
(append-char #\.)
'
98
(go-next default))
'
99
(camel-case
'
100
"Convert camelCase to lisp-style."
'
101
(if (upper-case-p char)
'
102
(progn
'
103
(append-char #\-)
'
104
(append-char char)
'
105
(go-next default))
'
106
(go default))))
'
107
'
108
'
109
(defmethod print-object ((object smoke-standard-object) stream)
2009-05-27 tobias
110
(if (slot-boundp object 'pointer)
17:22:08 '
111
(print-unreadable-object (object stream :type t)
'
112
(princ (pointer object) stream))
'
113
(call-next-method)))
2009-04-05 tobias
114
15:36:29 '
115
(defclass smoke-standard-class (standard-class smoke-class)
2009-05-24 tobias
116
()
2009-04-05 tobias
117
(:documentation "A Smoke C++ class"))
15:36:29 '
118
2009-05-31 tobias
119
(defclass cxx:class (smoke-standard-class)
2009-07-08 tobias
120
()
2009-05-31 tobias
121
(:documentation "Metaclass to extend Smoke Objects."))
2009-05-14 tobias
122
2009-08-02 tobias
123
(defmethod closer-mop:validate-superclass ((class smoke-standard-class) (superclass standard-class))
2009-07-22 tobias
124
t)
2009-04-05 tobias
125
2009-08-02 tobias
126
(defmethod closer-mop:validate-superclass ((class cxx:class) (superclass smoke-standard-class))
2009-07-22 tobias
127
t)
2009-04-05 tobias
128
2009-08-02 tobias
129
(defmethod reinitialize-instance :around
10:12:41 '
130
((class smoke-standard-class)
'
131
&rest args &key direct-superclasses &allow-other-keys)
'
132
(apply
'
133
#'call-next-method class
'
134
:direct-superclasses (or direct-superclasses
'
135
(list (find-class
'
136
'smoke-standard-object))) args))
2009-04-05 tobias
137
2009-08-02 tobias
138
(defmethod initialize-instance :around
10:12:41 '
139
((class smoke-standard-class)
'
140
&rest args &key direct-superclasses &allow-other-keys)
'
141
"Sets NIL superclass to SMOKE-STANDARD-OBJECT instead of the default STANDARD-OBJECT."
'
142
(apply
'
143
#'call-next-method class
'
144
:direct-superclasses (or direct-superclasses
'
145
(list (find-class 'smoke-standard-object)))
'
146
args))
2009-04-05 tobias
147
2009-08-02 tobias
148
(defmethod reinitialize-instance :around
10:12:41 '
149
((class cxx:class)
'
150
&rest args &key direct-superclasses &allow-other-keys)
'
151
(assert (not (null direct-superclasses))
'
152
(direct-superclasses)
'
153
"No superclass supplied for class ~A" class)
'
154
(let ((superclass (first direct-superclasses)))
'
155
(assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
'
156
((first direct-superclasses))
'
157
"The first superclass must be an subclass of an smoke class.")
'
158
(apply
'
159
#'call-next-method class
'
160
:id (id superclass)
'
161
:smoke (smoke superclass)
'
162
:direct-superclasses direct-superclasses
'
163
args)))
2009-04-05 tobias
164
2009-08-02 tobias
165
(defmethod initialize-instance :around
10:12:41 '
166
((class cxx:class)
'
167
&rest args &key direct-superclasses &allow-other-keys)
2009-04-05 tobias
168
(assert (not (null direct-superclasses))
15:36:29 '
169
(direct-superclasses)
2009-08-30 tobias
170
"No superclass sup-lied for class ~A" class)
14:12:44 '
171
(let ((superclass (first direct-superclasses)))
'
172
(assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
2009-04-05 tobias
173
((first direct-superclasses))
2009-08-30 tobias
174
"The first superclass must be an subclass of an smoke class.")
2009-06-10 tobias
175
(assert (virtual-destructor-p superclass)
11:55:55 '
176
()
2009-08-30 tobias
177
"The class ~A has a non virtual destructor." superclass)
2009-08-02 tobias
178
2009-04-05 tobias
179
(apply
2009-08-02 tobias
180
#'call-next-method class
2009-07-08 tobias
181
:id (id superclass)
2009-06-22 tobias
182
:smoke (smoke superclass)
2009-04-05 tobias
183
:direct-superclasses direct-superclasses
15:36:29 '
184
args)))
'
185
2010-01-26 tobias
186
(defun smoke-class-symbol (smoke-class)
16:26:09 '
187
"Returns the Lisp class-name of SMOKE-CLASS:"
'
188
(if (external-p smoke-class)
'
189
(class-name (find-smoke-class smoke-class))
'
190
(lispify (name smoke-class))))
2009-04-05 tobias
191
2009-08-30 tobias
192
2009-06-11 tobias
193
(defun make-smoke-classes (package smoke)
2009-07-01 tobias
194
"Constructs a lisp class in PACKAGE for each one in the Smoke module SMOKE."
2009-06-22 tobias
195
(declare (optimize (speed 3)))
2010-01-10 tobias
196
(let ((*package* (find-package package)))
2009-06-22 tobias
197
(add-id-class-map smoke)
2009-04-05 tobias
198
(map-classes
15:36:29 '
199
#'(lambda (class)
2009-08-27 tobias
200
(unless (external-p class)
11:43:13 '
201
(add-id class
'
202
(closer-mop:ensure-class (lispify (name class))
'
203
:direct-superclasses
'
204
(mapcar #'smoke-class-symbol
'
205
(smoke-class-direct-superclasses class))
'
206
:id (id class)
'
207
:smoke (smoke class)
'
208
:metaclass 'smoke-standard-class))
'
209
(export (lispify (name class)))))
2009-06-11 tobias
210
smoke)))
2009-04-05 tobias
211
2009-04-12 tobias
212
(defclass smoke-gf (cxx-generic-function)
14:43:33 '
213
((cxx-name :reader name :initarg :cxx-name
2009-05-11 tobias
214
:type string
11:07:39 '
215
:documentation "The C++ name of the method."))
2009-04-05 tobias
216
(:metaclass closer-mop:funcallable-standard-class)
2009-05-11 tobias
217
(:documentation "Smoke generic function."))
2009-04-05 tobias
218
2009-06-22 tobias
219
(declaim (inline smoke-class-of))
2009-04-05 tobias
220
(defun smoke-class-of (object)
2009-07-01 tobias
221
"Returns the class of OBJECT or OBJECT iff it already is a class."
2009-06-22 tobias
222
(declare (optimize (speed 3)))
12:18:08 '
223
(if (typep object 'smoke-class)
2009-04-05 tobias
224
object
15:36:29 '
225
(class-of object)))
'
226
2009-04-12 tobias
227
;;; To speed up the startup
2009-04-05 tobias
228
;;; ENSURE-METHOD is only called as needed.
15:36:29 '
229
(defmethod no-applicable-method ((gf smoke-gf) &rest args)
'
230
"Calls the smoke method."
2009-06-22 tobias
231
(declare (dynamic-extent args)
12:18:08 '
232
(optimize (speed 3)))
2009-04-17 tobias
233
(call-using-args (first args) (name gf) (rest args)))
2009-04-05 tobias
234
2009-04-12 tobias
235
(defmethod add-method :after ((gf cxx-method-generic-function) method)
2009-04-05 tobias
236
"Adds a method which calls the smoke method, to make call-next-method work."
15:36:29 '
237
(when (null (rest (closer-mop:generic-function-methods gf)))
2009-04-12 tobias
238
(let ((lambda-list (closer-mop:method-lambda-list method)))
14:43:33 '
239
(closer-mop:ensure-method
'
240
gf
'
241
`(lambda ,lambda-list
'
242
(declare (optimize (speed 3)))
2009-05-11 tobias
243
(call-using-args ,(first lambda-list)
17:55:42 '
244
(name ,(cxx-generic-function gf))
2009-05-11 tobias
245
(list ,@(rest lambda-list))))))))
2009-04-05 tobias
246
15:36:29 '
247
(defcallback destructed :void
2009-07-22 tobias
248
((object-pointer :pointer))
2009-06-22 tobias
249
(declare (optimize (speed 3)))
2009-04-05 tobias
250
(let ((object (get-object object-pointer)))
15:36:29 '
251
(when object
2009-06-30 tobias
252
(remove-finalizer object)
2009-04-05 tobias
253
(remove-object object-pointer)
15:36:29 '
254
(setf (slot-value object 'pointer) (null-pointer)))))
'
255
2009-06-22 tobias
256
(declaim (inline argument-to-lisp))
12:18:08 '
257
(defun argument-to-lisp (stack-item type)
'
258
;; FIXME do not take ownership of stack allocated objects.
'
259
(type-to-lisp stack-item type))
'
260
2009-04-05 tobias
261
(defun stack-to-args (stack arg &optional (args nil))
15:36:29 '
262
"Returns the arguments in STACK, where ARG is the type
'
263
of the first argument, as an list of Lisp objects."
'
264
(if (end-p arg)
2009-06-22 tobias
265
(reverse args)
12:18:08 '
266
(stack-to-args (inc-pointer stack
'
267
(foreign-type-size 'smoke-stack-item))
2009-04-05 tobias
268
(next arg)
2009-08-02 tobias
269
(push (argument-to-lisp (mem-ref stack
2009-07-22 tobias
270
'smoke-stack-item)
22:26:05 '
271
arg)
2009-06-22 tobias
272
args))))
2009-04-05 tobias
273
2009-09-02 tobias
274
(defun convert-argument (argument type &optional (user t))
11:49:34 '
275
"Returns ARGUMENT converted to TYPE. If USER is true, user defined
'
276
conversion sequences are considered."
'
277
(let ((rank (get-conversion-sequence argument type user)))
'
278
(if (null rank)
'
279
(error "Can not convert the argument ~S to ~A."
'
280
argument (name type))
'
281
(funcall (conversion-function-name rank)
'
282
argument))))
2009-04-05 tobias
283
2009-06-08 tobias
284
(defun put-returnvalue (stack value type object)
2009-04-05 tobias
285
(unless (void-p type)
2009-05-26 tobias
286
(let ((stack (make-call-stack stack)))
2009-07-08 tobias
287
(setf (call-stack-top stack) (call-stack-pointer stack))
2009-09-02 tobias
288
;; FIXME support user conversions.
2009-07-22 tobias
289
;;
2009-09-02 tobias
290
;; We need to determine which of value and converted-value is
2009-07-22 tobias
291
;; passed on the stack. E.g. converted-value can be something
22:26:05 '
292
;; like (cxx:operator-variant value).
2009-09-02 tobias
293
(let ((converted-value (convert-argument value type nil)))
11:49:34 '
294
(push-smoke-stack stack converted-value (type-id type))
'
295
(when (stack-p type) ;; Pass by value => smoke deletes the object.
'
296
(remove-finalizer converted-value)
'
297
(when (typep value 'smoke-standard-object)
2009-08-02 tobias
298
(transfer-ownership-to value object)))))))
2009-04-05 tobias
299
2009-05-19 tobias
300
(defun get-gf-for-method (smoke-method)
11:09:12 '
301
(declare (smoke-method smoke-method)
'
302
(optimize (speed 3)))
'
303
(symbol-function (lispify (name smoke-method) "CXX")))
2009-05-19 tobias
304
2009-04-05 tobias
305
(defcallback dispatch-method :boolean
2010-02-19 tobias
306
((binding :pointer)
21:10:24 '
307
(method smoke-index)
2009-06-30 tobias
308
(object-ptr :pointer)
22:47:39 '
309
(stack smoke-stack)
'
310
(abstract :boolean))
2009-04-05 tobias
311
(declare (optimize (speed 3)))
2009-06-30 tobias
312
(let ((object (get-object object-ptr)))
2009-08-02 tobias
313
;; FIXME:
10:12:41 '
314
;;(assert object
'
315
;; (object)
'
316
;; "No object for ~A to call ~A." object-ptr method)
'
317
(if (and object (typep (class-of object) 'cxx:class))
2009-07-22 tobias
318
;; Do not allow overwriting methods of classes the users has
22:26:05 '
319
;; not derived from (like in C++), to reduce overhead.
2009-08-02 tobias
320
(let* ((method (make-smoke-method
2009-07-22 tobias
321
:smoke (gethash (pointer-address
22:26:05 '
322
(smoke-get-smoke binding))
2009-08-02 tobias
323
*smoke-modules*)
10:12:41 '
324
:id method)))
'
325
(loop
'
326
(restart-case
'
327
(return-from dispatch-method
'
328
(let ((gf (get-gf-for-method method)))
'
329
(declare (function gf))
'
330
(if (null (gf-methods gf))
'
331
(progn
'
332
(when abstract
'
333
(error "Abstract method ~A called."
'
334
(method-declaration method)))
'
335
nil)
'
336
(if object
'
337
(progn
'
338
(put-returnvalue stack
'
339
(apply gf object
'
340
(stack-to-args
'
341
(inc-pointer stack
'
342
(foreign-type-size
'
343
'smoke-stack-item))
'
344
(get-first-argument method)))
'
345
(return-type method)
'
346
object)
'
347
t)
'
348
nil))))
'
349
;; Restarts to prevent stack unwinding across the C++ stack.
'
350
(call-default ()
'
351
:report (lambda (stream)
'
352
(declare (stream stream))
'
353
(format stream "Call default implementation ~A instead."
'
354
method))
'
355
:test (lambda (condition)
'
356
(declare (ignore condition))
'
357
(not abstract))
'
358
(return-from dispatch-method nil))
'
359
(use-returnvalue (return-value)
'
360
:report (lambda (stream)
'
361
(declare (stream stream))
'
362
(format stream "Supply a return value for ~A."
'
363
(method-declaration method)))
'
364
:test (lambda (condition)
'
365
(declare (ignore condition))
'
366
(not (void-p (return-type method))))
'
367
:interactive (lambda ()
'
368
(format *query-io* "~&Enter a new return value: ")
'
369
(multiple-value-list (eval (read *query-io*))))
'
370
(put-returnvalue stack return-value
'
371
(return-type method)
'
372
(get-object object-ptr))
'
373
(return-from dispatch-method t))
'
374
(return ()
'
375
:report (lambda (stream)
'
376
(declare (stream stream))
'
377
(format stream "Return void for ~A."
'
378
(method-declaration method)))
'
379
:test (lambda (condition)
'
380
(declare (ignore condition))
'
381
(void-p (return-type method)))
'
382
(return-from dispatch-method (values)))
'
383
(retry ()
'
384
:report (lambda (stream)
'
385
(declare (stream stream))
'
386
(format stream "Try again calling ~A."
'
387
(method-declaration method))))))
'
388
nil))))
2009-04-05 tobias
389
15:36:29 '
390
;;FIXME use CHANGE-CLASS instead?
2009-08-30 tobias
391
(defun cast (object class)
14:12:44 '
392
"Returns a pointer of type CLASS to the C++ object of OBJECT."
2009-07-08 tobias
393
(declare (optimize (speed 3)))
2009-08-30 tobias
394
(assert (derived-p (class-of object) class)
14:12:44 '
395
()
'
396
"Can not cast object ~A of class ~A to class ~A."
'
397
object (name (class-of object)) (name class))
'
398
(smoke-cast (smoke-module-pointer (smoke (class-of object))) (pointer object)
'
399
(id (class-of object)) (id class)))
'
400
2009-04-05 tobias
401
15:36:29 '
402
(defun upcast (object class)
'
403
(assert (derived-p class (class-of object))
'
404
()
'
405
"Can not upcast object ~A of class ~A to class ~A."
'
406
object (name (class-of object)) (name class))
2009-06-22 tobias
407
(smoke-cast (smoke-module-pointer (smoke class)) (pointer object)
2009-04-05 tobias
408
(id (class-of object)) (id (real-class class))))
15:36:29 '
409
'
410
2009-08-02 tobias
411
(defmethod convert-to-class (smoke-class (object smoke-standard-object))
10:12:41 '
412
(cast object smoke-class))
'
413
2009-07-22 tobias
414
(defun constructor-name (class)
22:26:05 '
415
(let ((name-start (search "::" (name class) :from-end t)))
'
416
(if name-start
'
417
(subseq (name class) (+ name-start 2))
'
418
(name class))))
'
419
2009-08-30 tobias
420
(defun call-constructor (object arguments)
14:12:44 '
421
(if (null arguments)
'
422
(let ((method (find-smoke-method (class-of object)
2009-07-22 tobias
423
(constructor-name (class-of object)))))
22:26:05 '
424
(assert (valid-p method)
'
425
(method)
'
426
"No constructor for ~A." object)
2009-08-30 tobias
427
(pointer-call method (null-pointer)))
14:12:44 '
428
(multiple-value-bind (method sequence)
2009-07-22 tobias
429
(find-best-viable-function (constructor-name (class-of object))
2009-08-30 tobias
430
arguments
14:12:44 '
431
(class-of object))
'
432
(when (null method)
2009-07-22 tobias
433
(error "No constructor for object ~A with
22:26:05 '
434
the arguments ~S." object arguments))
2009-08-30 tobias
435
(pointer-call method (null-pointer)
14:12:44 '
436
(mapcar #'(lambda (conversion argument)
'
437
(funcall conversion argument))
'
438
sequence arguments)))))
2009-04-05 tobias
439
15:36:29 '
440
(defmethod initialize-instance :after ((object smoke-standard-object)
2009-07-22 tobias
441
&key args
22:26:05 '
442
(arg0 nil arg0p)
'
443
(arg1 nil arg1p)
'
444
(arg2 nil arg2p)
'
445
&allow-other-keys)
2009-04-05 tobias
446
"Initializes a Smoke object. Calls its constructor with the arguments supplied
15:36:29 '
447
by the key :ARGS and sets the smoke binding."
2009-06-22 tobias
448
(declare (optimize (speed 3)))
2009-04-05 tobias
449
(assert (not (and (slot-boundp object 'pointer)
15:36:29 '
450
(not (null args))))
'
451
((slot-value object 'pointer) args)
'
452
"Pointer ~A bound and constructor argument :ARGS ~S supplied."
'
453
(slot-value object 'pointer) args)
'
454
(unless (slot-boundp object 'pointer)
2009-07-22 tobias
455
(if arg0p
22:26:05 '
456
(setf (slot-value object 'pointer)
'
457
(call-constructor object
'
458
(cond
'
459
(arg2p (list arg0 arg1 arg2))
'
460
(arg1p (list arg0 arg1))
'
461
(t (list arg0)))))
'
462
(setf (slot-value object 'pointer) (call-constructor object args)))
2009-06-22 tobias
463
(set-binding object)
2009-05-24 tobias
464
(take-ownership object)
2009-04-05 tobias
465
(add-object object)))
15:36:29 '
466
'
467
'
468
(defmethod instance-to-lisp (pointer class type)
2009-06-22 tobias
469
(declare (type smoke-standard-class class)
12:18:08 '
470
(optimize (speed 3)))
2009-08-27 tobias
471
(let ((ret (make-instance class :pointer pointer)))
2009-05-24 tobias
472
(when (stack-p type)
11:30:05 '
473
(take-ownership ret)
'
474
(add-object ret))
2009-04-05 tobias
475
ret))
2009-05-31 tobias
476
2009-06-08 tobias
477
(defun keep-wrapper (object new-owner)
2009-06-22 tobias
478
(declare (type smoke-standard-object object)
12:18:08 '
479
(optimize (speed 3)))
2009-06-10 tobias
480
(when (member object (owned-objects new-owner))
2009-08-02 tobias
481
(cerror "ignore" "~A has already been called for ~A."
10:12:41 '
482
#'keep-wrapper object))
2009-06-08 tobias
483
(push object (owned-objects new-owner)))
2009-05-31 tobias
484
2009-06-22 tobias
485
(declaim (inline remove-wrapper-object))
2009-06-08 tobias
486
(defun remove-wrapper-object (object owner)
09:20:54 '
487
(remove object (owned-objects owner)))
2009-05-31 tobias
488
2009-06-08 tobias
489
(defun transfer-ownership-to (object new-owner)
2009-05-31 tobias
490
"Transfers the ownership of OBJECT to C++."
2009-06-22 tobias
491
(declare (optimize (speed 3)))
2009-06-30 tobias
492
(remove-finalizer object)
2009-06-10 tobias
493
(if (virtual-destructor-p (class-of object))
11:55:55 '
494
(keep-wrapper object new-owner)
'
495
(remove-object (pointer object))))
2009-05-31 tobias
496
2009-06-08 tobias
497
(defun take-ownership (object &optional current-owner)
2009-05-31 tobias
498
"Assigns the ownership of OBJECT to Lisp. i.e.:
17:41:26 '
499
cl-smoke is responsible for deleting the object."
2009-06-08 tobias
500
(when current-owner
09:20:54 '
501
(remove-wrapper-object object current-owner))
2009-06-30 tobias
502
(set-finalizer object))