[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