[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GSObjRuntime patches...

From: David Ayers
Subject: Re: GSObjRuntime patches...
Date: Wed, 09 Jun 2004 11:03:15 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040514

Marc Ordinas i Llopis wrote:

Hi, everyone,

It would be really, really helpful for everyone else if people with CVS write permission would at least try to describe the changes they commit. Adam Fedor's gnustep-cvs hack certainly does help, but it's not sufficient to track what's going on if commiters don't explain it to the list(s).

Hello Marc,

I tend to agree. I was hoping that in this case the documentation which was part of the patch was sufficient. But I guess it could use some more introduction. So here's the long story...

My concrete problem was that Foundation implements certain categories that are also implemented in GDL2. Now category precedence is undefined by ObjC and in fact the GDL2 categories were pretty consistently ignored on Cocoa in one particular application. But for GDL2 to work, we need to make sure our categories are active.

First step was a way to identify the method list which corresponds to my category. For this I implement a dummy method in my category and use the new:
GSMethodListForSelector(Class class,
                        SEL selector,
                        void **iterator,
                        BOOL searchInstanceMethods);
function to retrieve the list.
(Note that instance and class methods are in separate method list, so if you have both instance and class methods you'll need to handle instance and class methods separately.)

Second I remove the method list from from class with:
GSRemoveMethodList(Class class,
                   GSMethodList list,
                   BOOL fromInstanceMethods);
and add it again with:
GSAddMethodList(Class class,
                GSMethodList list,
                BOOL toInstanceMethods);
as this function should add the list in such a way that it becomes the "active" method list and there for these methods will take precedence.

For finer granularity (manipulating method structures within a list) you can use:
GSMethodFromList(GSMethodList list,
                 SEL sel,
                 BOOL isFree);
Which should return the "active" implementation of a method and then you can start exchanging the pointers in the struct objc_method pointed to by GSMethod.

Note that after any runtime manipulations like this, the class caches should be cleared by calling:
GSFlushMethodCacheForClass (Class class);

In repository driven applications (or large GDL2 applications that have lots of similar methods like standard object accessor methods with common offsets yet different ivars) it can be of interest to share implementations independent of class hierarchy and create method lists at runtime.

For this you can use:
GSAllocMethodList (unsigned int count);

to create a method list which my contain count methods. Then you start filling the method list with:
GSAppendMethodToList (GSMethodList list,
                      SEL sel,
                      const char *types,
                      IMP imp,
                      BOOL isFree);
Where "imp" can be a pointer from an implementation from a template class or even a function (which must take the hidden parameters self and _cmd).

To complete the API I added:
GSRemoveMethodFromList (GSMethodList list,
                        SEL sel,
                        BOOL isFree);

Actually GSObjCAddClassBehavior needs similar functionality when copying behavior from one class to another. It also needs to take care not to override methods that are already implemented in the class and certain special cases like +initialize and +load. After the release of base, I'll update GSObjCAddClassBehavior to use the new functions.

I hope you can get the rest of the information from the documentation. How's that?


reply via email to

[Prev in Thread] Current Thread [Next in Thread]