-
-#define CF_IS_OBJC(typeID, obj) (false)
-
-#define CF_OBJC_VOIDCALL0(obj, sel)
-#define CF_OBJC_VOIDCALL1(obj, sel, a1)
-#define CF_OBJC_VOIDCALL2(obj, sel, a1, a2)
-
-#define CF_OBJC_CALL0(rettype, retvar, obj, sel)
-#define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1)
-#define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2)
-
-#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel)
-#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1)
-#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2)
-#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3)
-#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4)
-#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5)
+// Invoke an ObjC method that returns void.
+// Assumes CF_IS_OBJC has already been checked.
+#define CF_OBJC_VOIDCALL0(obj, sel) \
+ {void (*func)(const void *, SEL) = (void (*)(const void *, SEL))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ func((const void *)obj, s);}
+#define CF_OBJC_VOIDCALL1(obj, sel, a1) \
+ {void (*func)(const void *, SEL, ...) = (void (*)(const void *, SEL, ...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ func((const void *)obj, s, (a1));}
+#define CF_OBJC_VOIDCALL2(obj, sel, a1, a2) \
+ {void (*func)(const void *, SEL, ...) = (void (*)(const void *, SEL, ...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ func((const void *)obj, s, (a1), (a2));}
+
+
+// Invoke an ObjC method, leaving the result in "retvar".
+// Assumes CF_IS_OBJC has already been checked.
+#define CF_OBJC_CALL0(rettype, retvar, obj, sel) \
+ {rettype (*func)(const void *, SEL) = (rettype (*)(const void *, SEL))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ retvar = func((const void *)obj, s);}
+#define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL, ...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ retvar = func((const void *)obj, s, (a1));}
+#define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL, ...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ retvar = func((const void *)obj, s, (a1), (a2));}
+
+// Invoke an ObjC method, return the result
+#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL) = (rettype (*)(const void *, SEL))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s);}
+#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s, (a1));}
+#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s, (a1), (a2));}
+#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s, (a1), (a2), (a3));}
+#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s, (a1), (a2), (a3), (a4));}
+#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5) \
+ if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
+ {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \
+ static SEL s = NULL; if (!s) s = sel_registerName(sel); \
+ return func((const void *)obj, s, (a1), (a2), (a3), (a4), (a5));}