Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Destructors for CLOS objects

87 views
Skip to first unread message

Philippe Gagné

unread,
Dec 11, 2001, 11:42:44 AM12/11/01
to
I am starting to play with Lisp as a means to develop vision algorithms. I
have some c++ libraries that I export in a dll. I made a number of stubs
that make the mapping between C++ and C. They look like :

typedef void * handle;

handle NewObject()
{
return (handle) new CMyObject;
}

void DeleteObject(handle obj)
{
delete (CMyObject*)obj;
}

int FnObject(handle obj, int a)
{
return ((CMyObject*)obj)->Fn(a);
}

etc.

I use Corman lisp to read the ".h" file of the DLL and it works ! My lisp
interpreter now have 3 fonctions CMyObject_NewObject, CMyObject_DeleteObject
and DeleteObject_FnObject.

I now want to encapsulate all those fonctions in a Lisp object. I am a
beginner in Lisp. As I understand CLOS, I need to define the class :

(defclass CMyObject ()
((handle :initform (CMyObjec_New)))
)

Then at make-instance, I will obtain a new handle. But I can't find where I
plug a CMyObject_Destroy in a class definition i.-e. where is the equivalent
of a destroctor in CLOS ?

By the way, is there a way to dynamically link a DLL in CLisp ?

Phil
phi....@videotron.ca

Barry Margolin

unread,
Dec 11, 2001, 12:12:29 PM12/11/01
to
In article <tDqR7.10619$eF1.1...@news20.bellglobal.com>,

Philippe Gagné <pga...@criq.qc.ca> wrote:
>Then at make-instance, I will obtain a new handle. But I can't find where I
>plug a CMyObject_Destroy in a class definition i.-e. where is the equivalent
>of a destroctor in CLOS ?

There isn't any such thing, since Lisp doesn't require explicit storage
reclamation, it uses a garbage collector. If your application requires you
to tell the class when you're done with the object so it can perform
additional tasks (like closing files) you can define your own generic
function for this, and require the calling application to call it. You
might also want to provide a macro that does it automatically, e.g.

(defmacro with-my-object ((var &rest init-options) &body body)
(let (,var)
(unwind-protect
(progn (setq ,var (make-instance 'my-object ,@init-options))
,@body)
(unless (null ,var)
(delete-my-object ,var)))))

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Thomas F. Burdick

unread,
Dec 11, 2001, 7:09:55 PM12/11/01
to
Barry Margolin <bar...@genuity.net> writes:

> In article <tDqR7.10619$eF1.1...@news20.bellglobal.com>,
> Philippe Gagné <pga...@criq.qc.ca> wrote:
> >Then at make-instance, I will obtain a new handle. But I can't find where I
> >plug a CMyObject_Destroy in a class definition i.-e. where is the equivalent
> >of a destroctor in CLOS ?
>
> There isn't any such thing, since Lisp doesn't require explicit storage
> reclamation, it uses a garbage collector. If your application requires you
> to tell the class when you're done with the object so it can perform
> additional tasks (like closing files) you can define your own generic
> function for this, and require the calling application to call it. You
> might also want to provide a macro that does it automatically, e.g.
>
> (defmacro with-my-object ((var &rest init-options) &body body)
> (let (,var)

^should be a backquote here


> (unwind-protect
> (progn (setq ,var (make-instance 'my-object ,@init-options))
> ,@body)
> (unless (null ,var)
> (delete-my-object ,var)))))

This is how we (usually) solve the problem of freeing resources
associated with an object in Lisp. Although, I'd have written that
macro as:

(defmacro with-my-object ((var &rest init-options) &body body)

(let ((obj (gensym)))
`(let (,var ,obj)
(unwind-protect
(progn (setq ,obj (make-instance 'my-object ,@init-options)
,var ,obj)
,@body)
(unless (null ,obj)
(delete-my-object ,obj))))))

So as to not leak the object if the user of with-my-object setq's var.

As for objects that don't manage resources that need to be freed in a
timely manner, if Corman Lisp's GC has finalizers, you can use those
to run your destructors. This is the best use I know of for finalizers:
to free memory managed outside of the GC.

--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Rolf Wester

unread,
Dec 13, 2001, 3:56:01 AM12/13/01
to

"Thomas F. Burdick" schrieb:

Hi,

I'm just a Lisp beginner, so I'm not sure wether I'm right. But shouldn't it read:

(defmacro with-my-object ((var &rest init-options) &body body)
(let ((obj (gensym)))

`(let (,obj ,var)
instead of `(let (,var ,obj)

If I'm wrong please correct me.

Rolf Wester

Kent M Pitman

unread,
Dec 13, 2001, 4:19:47 AM12/13/01
to
Rolf Wester <wes...@ilt.fhg.de> writes:

> > This is how we (usually) solve the problem of freeing resources
> > associated with an object in Lisp. Although, I'd have written that
> > macro as:
> >
>
> >
> > (defmacro with-my-object ((var &rest init-options) &body body)
> > (let ((obj (gensym)))
> > `(let (,var ,obj)
> > (unwind-protect
> > (progn (setq ,obj (make-instance 'my-object ,@init-options)
> > ,var ,obj)
> > ,@body)
> > (unless (null ,obj)
> > (delete-my-object ,obj))))))
> >
>
> Hi,
>
> I'm just a Lisp beginner, so I'm not sure wether I'm right.
> But shouldn't it read:
>
> (defmacro with-my-object ((var &rest init-options) &body body)
> (let ((obj (gensym)))
> `(let (,obj ,var)
> instead of `(let (,var ,obj)
>
> If I'm wrong please correct me.

You happen to be wrong, but the real reason is that you're missing the point.

The syntax (let (a b) ...) does not give a the value resulting from evaluating
b, but instead binds the variables a and b each to NIL.

You are thinking it says (let ((a b)) ...) in which case the order would
matter. Since both are variables and one is not the initial value of the
other, the order is irrelevant.

Now with the knowledge that he's binding two variables, one of which is
a gensym inaccessible to the program other than setq and the unwind-protect
cleanup clause you see there (and so protected from the program reassigning
the variable) and one of which is a user-level variable that might be later
redefined with no ill effects, go back and read the program again and see
if it makes sense to you. Because the order of binding two variables to NIL
doesn't matter, you can use either (let (,obj ,var) ...) or
(let (,var ,obj) ...) and you should get the same result.

Coby Beck

unread,
Dec 13, 2001, 4:21:24 AM12/13/01
to

"Rolf Wester" <wes...@ilt.fhg.de> wrote in message
news:3C186D21...@ilt.fhg.de...
>
>
> "Thomas F. Burdick" schrieb:

>
> > (defmacro with-my-object ((var &rest init-options) &body body)
> > (let ((obj (gensym)))
> > `(let (,var ,obj)
> > (unwind-protect
> > (progn (setq ,obj (make-instance 'my-object ,@init-options)
> > ,var ,obj)
> > ,@body)
> > (unless (null ,obj)
> > (delete-my-object ,obj))))))
> >
>
> Hi,
>
> I'm just a Lisp beginner, so I'm not sure wether I'm right. But shouldn't it
read:
>
> (defmacro with-my-object ((var &rest init-options) &body body)
> (let ((obj (gensym)))
> `(let (,obj ,var)
> instead of `(let (,var ,obj)
>
> If I'm wrong please correct me.
>

I believe you're right!

--
Coby
(remove #\space "coby . beck @ opentechgroup . com")


Thomas F. Burdick

unread,
Dec 13, 2001, 4:33:24 AM12/13/01
to
Rolf Wester <wes...@ilt.fhg.de> writes:

> "Thomas F. Burdick" schrieb:


>
> > (defmacro with-my-object ((var &rest init-options) &body body)
> > (let ((obj (gensym)))
> > `(let (,var ,obj)
> > (unwind-protect
> > (progn (setq ,obj (make-instance 'my-object ,@init-options)
> > ,var ,obj)
> > ,@body)
> > (unless (null ,obj)
> > (delete-my-object ,obj))))))
> >
>
> Hi,
>
> I'm just a Lisp beginner, so I'm not sure wether I'm right. But
> shouldn't it read:
>
> (defmacro with-my-object ((var &rest init-options) &body body)
> (let ((obj (gensym)))
> `(let (,obj ,var)
>
> instead of `(let (,var ,obj)

There's no difference. The outer LET is binding OBJ to a gensym. The
backquoted LET will bind the gensym that OBJ is bound to, to NIL.
Same for the symbol VAR is bound to. They're both bound in parallel,
and both are assigned to later.

(let (x y) ...)
(let (y x) ...)
(let ((x ...) (y ...)) ...) ; [*]
(let ((y ...) (x ...)) ...) ; [*]

are all equivalent. For the ones marked [*], this is only true if the
value forms don't have side effects, but that's not material to your
confusion above.

* (let ((x 10))
(let ((x (incf x))
(y (incf x)))
(values x y)))
11
12
* (let ((x 10))
(let ((y (incf x))
(x (incf x)))
(values x y)))
12
11
* (let ((a 10))
(let (x y)
(setf x (1+ a)
y (1+ a))
(values x y)))
11
11
* (let ((a 10))
(let (y x)
(setf x (1+ a)
y (1+ a))
(values x y)))
11
11


> If I'm wrong please correct me.
>
> Rolf Wester

--

Erik Naggum

unread,
Dec 13, 2001, 5:13:46 AM12/13/01
to
* Rolf Wester <wes...@ilt.fhg.de>

| I'm just a Lisp beginner, so I'm not sure wether I'm right. But shouldn't it read:
|
| (defmacro with-my-object ((var &rest init-options) &body body)
| (let ((obj (gensym)))
| `(let (,obj ,var)
| instead of `(let (,var ,obj)
|
| If I'm wrong please correct me.

There is a huge difference between ((foo bar)) and (foo bar) in let. The
former binds foo to the current value of bar. The latter binds foo and
bar to nil, the default value in absence of a value in a binding, and the
order is thus immaterial.

///
--
The past is not more important than the future, despite what your culture
has taught you. Your future observations, conclusions, and beliefs are
more important to you than those in your past ever will be. The world is
changing so fast the balance between the past and the future has shifted.

Coby Beck

unread,
Dec 14, 2001, 11:11:03 AM12/14/01
to

"Coby Beck" <cb...@mercury.bc.ca> wrote in message
news:oq_R7.87092$Ga5.13...@typhoon.tampabay.rr.com...

>
> "Rolf Wester" <wes...@ilt.fhg.de> wrote in message
> news:3C186D21...@ilt.fhg.de...
> >
> >
> > I'm just a Lisp beginner, so I'm not sure wether I'm right. But shouldn't
it
> read:
> >
> > (defmacro with-my-object ((var &rest init-options) &body body)
> > (let ((obj (gensym)))
> > `(let (,obj ,var)
> > instead of `(let (,var ,obj)
> >
> > If I'm wrong please correct me.
> >
>
> I believe you're right!
>

oops.


Kent M Pitman

unread,
Dec 14, 2001, 11:36:45 AM12/14/01
to
"Coby Beck" <cb...@mercury.bc.ca> writes:

Hey, your statement was not wrong. You were probably correct that you
believed it. Beliefs change. ;)

0 new messages