Hi guys,
Below, you will find a diff for the GNU Objective-C runtime which:
- Allows classes to implement a completely new dispatch mechanism
(for language bridges, or just plain perverseness)
- Doesn't break binary compatibility.
To use it, your class needs a method like this:
+ (IMP) messageLookupForSelector:(SEL)aSelector
This takes a selector, and returns a function which implements it.
This will only be checked if the class has the CUSTOMMESSAGEDISPATCH
flag set. If you include objc-api.h, you can set this in the
following way:
+ (void) initialize
{
CLS_SETCUSTOMMESSAGEDISPATCH(self);
}
Another option, which is more likely to be useful for language like
Io, is to use the alternate form. Here, the method to implement is:
+ (IMP) messageLookupForObject:(id)anObject selector:(SEL)aSelector
And the initialisation should be:
+ (void) initialize
{
CLS_SETOBJECTMESSAGEDISPATCH(self);
}
This allows you to redefine messaging semantics on a per-object
basis, so each Io object could have its own dtable in an ivar, and
use this for overriding methods in the class.
Note: Writing a replacement dispatch mechanism is not hard, but it
is certainly nontrivial. Expect things to break the first time you
try it :-)
David
P.S. After some testing, could someone with GNUstep commit access
push this upstream to the GNUstep libobjc? The FSF have my copyright
assignment form.
Index: sendmsg.c
===================================================================
--- sendmsg.c (revision 25522)
+++ sendmsg.c (working copy)
@@ -221,6 +221,36 @@
IMP result;
if (receiver)
{
+ /* Check for per-object dispatch */
+ if(CLS_ISOBJECTMESSAGEDISPATCH(receiver->class_pointer))
+ {
+ static SEL selector = NULL;
+ if (selector == NULL)
+ {
+ selector = sel_get_any_uid
("messageLookupForObject:selector:");
+ }
+ IMP alternate = objc_msg_lookup ((id)receiver-
>class_pointer, selector);
+ if (alternate != NULL)
+ {
+ return (IMP)alternate ((id)receiver->class_pointer,
selector, receiver, op);
+ }
+ }
+
+ /* Check for a custom message lookup mechanism */
+ if(CLS_ISCUSTOMMESSAGEDISPATCH(receiver->class_pointer))
+ {
+ static SEL selector = NULL;
+ if (selector == NULL)
+ {
+ selector = sel_get_any_uid
("messageLookupForSelector:");
+ }
+ IMP alternate = objc_msg_lookup ((id)receiver-
>class_pointer, selector);
+ if (alternate != NULL)
+ {
+ return (IMP)alternate ((id)receiver->class_pointer,
selector, op);
+ }
+ }
+
result = sarray_get_safe (receiver->class_pointer->dtable,
(sidx)op->sel_id);
if (result == 0)
Index: objc/objc-api.h
===================================================================
--- objc/objc-api.h (revision 25522)
+++ objc/objc-api.h (working copy)
@@ -304,6 +304,20 @@
#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
/*
+** The class handles message dispatch on its own.
+*/
+#define _CLS_CUSTOMMESSAGEDISPATCH 0x10L
+#define CLS_ISCUSTOMMESSAGEDISPATCH(cls) __CLS_ISINFO(cls,
_CLS_CUSTOMMESSAGEDISPATCH)
+#define CLS_SETCUSTOMMESSAGEDISPATCH(cls) __CLS_SETINFO(cls,
_CLS_CUSTOMMESSAGEDISPATCH)
+
+/*
+** The class handles message dispatch differently for different
instances.
+*/
+#define _CLS_OBJECTMESSAGEDISPATCH 0x10L
+#define CLS_ISOBJECTMESSAGEDISPATCH(cls) __CLS_ISINFO(cls,
_CLS_OBJECTMESSAGEDISPATCH)
+#define CLS_SETOBJECTMESSAGEDISPATCH(cls) __CLS_SETINFO(cls,
_CLS_OBJECTMESSAGEDISPATCH)
+
+/*
** The class number of this class. This must be the same for both the
** class and its meta class object
*/
_______________________________________________
Etoile-dev mailing list
[email protected]
https://mail.gna.org/listinfo/etoile-dev