[Openmcl-devel] Trouble defining ObjC classes with struct slots
Daniel Dickison
danieldickison at gmail.com
Fri May 25 10:31:26 PDT 2007
On May 23, 2007, at 6:45 PM, Gary Byers wrote:
>
> On Wed, 23 May 2007, Daniel Dickison wrote:
>>
>> 1. If I define the slot to have a :foreign-type of :<NSP>oint, then
>> when I access the slot I get a generic foreign pointer which is not
>> recognized as an :<NSP>oint.
>
> There should be something like
>
> (ASSERT-FOREIGN-POINTER_TYPE <p> <foreign-type>),
> (which does what RLET and MAKE-RECORD do), and SLOT-VALUE (which
> pretty
> much has to cons up a MACPTR in cases like this).
>
> (assert-foreign-pointer-type (slot-value (make-instance 'a-point)
> 'point)
> :<NSP>oint)
>
> #<NS-POINT 5.180654D-318,0 (#x122B56A0) #x300041AA69DD>
Thanks! That would indeed be useful -- I'll keep that technique in
mind.
>>
>> 2. If I define the slot to be a CLOS slot (i.e. no :foreign-type
>> option), then I can store NSPoints in the slot and get back NSPoints
>> as expected, BUT, any initialization I do during the ObjC -init
>> method gets overridden by the :initform. It seems that CLOS slots
>> get re-initialized after the ObjC -init method runs, so the ObjC
>> initializations get wiped out.
>
> I think that that's a bug, but there are some chicken-and-egg issues
> here. (In order to be able to refer to the object's lisp slots from an
> ObjC init method, it's necessary to run INITIALIZE-INSTANCE - with no
> initargs - so that the slots' initforms are executed. The ObjC init
> method is often called (as part of ALLOCATE-INSTANCE) by
> MAKE-INSTANCE, which then turns around and does INITIALIZE-INSTANCE
> with initargs. That shouldn't cause any slots to be "initialized
> twice", but it's certainly unintuitive that INITIZLIZE-INSTANCE
> should run twice per instance (and it probably offers ways to lose.))
>
> The bug is that ALLOCATE-INSTANCE creates a "slots vector" for
> the instance even if one was created by virtue of the fact that
> a lisp slot was referenced in an ObjC #/init method.)
>
I admit this is CLOS territory I haven't seen before, so bear with
me... I'm still trying get my head wrapped around how this all
works. So here's my understanding:
- INITIALIZE-INSTANCE is called with no arguments if an object's
slots are accessed for the first time.
- ALLOCATE-INSTANCE calls #/init or it's equivalent by using non-
initarg keyword arguments.
- If the #/init method accesses a Lisp slot, then INITIALIZE-
INSTANCE is called with no arguments.
- MAKE-INSTANCE calls INITIALIZE-INSTANCE with all the args after
ALLOCATE-INSTANCE (and #/alloc #/init, etc).
- If you call (#/init (#/alloc foo)) "by hand" (or by any external
non-Lisp code), then INITIALIZE-INSTANCE is only called when slots
are first accessed, which could be much later on.
So (if I'm on the right track), if you have Lisp slots in an ObjC
class, and you need to initialize them in some way, you can either do
it in the #/init method or the INITIALIZE-INSTANCE :after method. If
you do it in the #/init method, then you shouldn't use MAKE-INSTANCE
to create instances because the slot initializations you did in #/
init will be obliterated by the default primary INITIALIZE-INSTANCE.
On the other hand, if you do the slot initialization in an INITIALIZE-
INSTANCE :after method, then you should always use MAKE-INSTANCE to
create instances -- but this doesn't work if you want foreign code to
be able to create instances and you need to use arguments in the
initializer.
It seems unintuitive that there are 2 distinct and incompatible ways
to initialize ObjC objects, and it feels like it could be made more
consistent. For example, instead of calling #/init or the like
during ALLOCATE-INSTANCE, it could just call #/alloc and INITIALIZE-
INSTANCE could call the #/init method -- I presume this doesn't work
because #/init can return a different object than self and ALLOCATE-
INSTANCE needs the final object... But now I'm confused how doing (#/
init (#/alloc foo)) manually can work properly if ALLOCATE-INSTANCE
has to do important work on the instance to make it a proper CLOS
object.
Sorry about the long email. My immediate problems are solved so now
I'm just writing out of curiosity.
Daniel
More information about the Openmcl-devel
mailing list