>
>> If the Garbage Collector is not clever enough to do that, it seems 
>> reasonable that the CGRect object might create references to a 
>> CGPoint object and a CGSize object within itself...
>
> Not sure I follow you here. Ruby only knows what you tell it about 
> your extension module's classes. For example, even though /you/ know 
> that a CGRect object contains references to a CGPoint and a CGSize, 
> Ruby doesn't deduce that. This is part of the motivation for writing a 
> "mark" function for your extension objects; the garbage collector 
> calls that mark function to ask, say, your CGRect object what /other/ 
> Ruby objects are reachable from there. In your case, you'd want to be 
> sure to call rb_gc_mark() for the Ruby objects that are wrapping the 
> CGPoint and CGSize objects:
>
>     void mark_CGRect(CGRect *rect)
>     {
>         VALUE pointObj, sizeObj;
>         pointObj = rubyObjectFor(rect->origin);
>         sizeObj = rubyObjectFor(rect->size);
>         rb_gc_mark(pointObj);
>         rb_gc_mark(sizeObj);
>     }

The problem I'm running into is in the mark routine for a CGSize object 
that was created as part of a CGRect.  The tricky part is that when my 
mark routine is called, it recieves a pointer to the CGSize structure 
in C.  I don't have any way to go from that pointer to a CGSize, to a 
pointer to a CGRect, to VALUE that represents the CGRect object.  To 
put it another way, given a pointer to a CGSize _structure_, I don't 
have a way to recover the CGRect _object_ that contains that structure.

In the original message I was talking about code like this:

VALUE rb_CGRect_initialize(VALUE self)
{
     CGRect *owningRect = NULL;

     Data_Get_Struct(self, CGRect, owningRect);

     if(NULL != owningRect) {
         VALUE originObject = Data_Wrap_Struct(
                                 gClass_CGPoint,
                                 0,
                                 0,
                                 &(owningRect->origin));

         VALUE sizeObject = Data_Wrap_Struct(
                                 gClass_CGSize,
                                 0,
                                 0,
                                 &(owningRect->size));

         rb_iv_set(self, "@size", sizeObject);
         rb_iv_set(self, "@origin", originObject);

         rb_iv_set(sizeObject, "@parentRect", self);
         rb_iv_set(originObject, "@parentRect", self);
     }
     return self;
}

This is the initialize method for CGRect.  In the initialize method, I 
define two instance variables "@size" and "@origin" that are part of 
the CGRect object.  At the same time, I set instance variables in the 
size and origin objects that point back to the rectangle.

My theory is as follows:

1) When ruby is trying to mark the CGRect it will "automagically" mark 
all of it's instance variables so the size and origin objects will get 
marked.
2) Similarly, when ruby tries to mark a size or origin object that has 
a parent rectangle, it will "automagically" mark the parent rectangle 
as well (preventing it from being Garbage Collected).
3) if neither the CGRect nor the CGSize/CGPoint have "external 
references" then none of the objects will be marked and the GC can suck 
up the whole tangled mess in one swell foop.

That way, if there are "external references"  to the CGRect, everybody 
gets marked.  If there are no "external references" to the CGRect, but 
there are "external references" to the size, or the origin, the CGRect 
will still get marked so it's memory won't be reclaimed.

Will that work out or am I trying to do things the hard way?

Scott