CrimsonChris CrimsonChris - 12 days ago 8
Objective-C Question

objc_msgSend macro on arm64

I'm trying to understand the difference between

id objc_msgSend(id self, SEL op, ...)
and
void objc_msgSend(void)


I have this macro that worked for methods of all types. However, when transitioning to arm64, this version of objc_msgSend is no longer available.

#define safePerformSelector(target, selector, ...) ([target respondsToSelector:selector] ? objc_msgSend(target, selector, ##__VA_ARGS__) : nil)


This is what I've come up with so far but it seems to only work for methods that return an object and fails for those that don't.

#define safePerformSelector(target, selector, ...) ([target respondsToSelector:selector] ? ((id (*)(id, SEL, ...))objc_msgSend)(target, selector, ##__VA_ARGS__) : nil)

Answer

You must always cast objc_msgSend() to the correct function pointer type first. Type id(*)(id, SEL, ...) is not the correct type, unless your method really does return id and accept ... (which IIRC is syntactically impossible).

If you call objc_msgSend() with an incorrect function type then the called method may not receive parameter values correctly.