<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Abusing Objective C With Class</title>
	<atom:link href="http://www.red-sweater.com/blog/320/abusing-objective-c-with-class/feed" rel="self" type="application/rss+xml" />
	<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class</link>
	<description>Mac &#38; Technology Writings by Daniel Jalkut</description>
	<pubDate>Fri, 21 Nov 2008 07:03:41 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
		<item>
		<title>By: Simon</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-84985</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Tue, 17 Apr 2007 22:10:33 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-84985</guid>
		<description>I've spent far more hours than I want to think about debugging stack corruption resulting from incorrect casts of function pointers and pointers-to-members.

I'm currently porting Win32/MFC code (in my Windows-bound day job) from Visual C++ 6.0 to Visual Studio 2005. This problem is particularly insidious with MFC's message map macros of old which are full of yummy (and decidedly dodgy) casting.

Making assumptions about function prototypes, calling conventions, return types at the C level is always a bad idea.

Apple provides a solution with NSInvocation and it even lets you check the size of the return type against your expectations, so I'd prefer to go with that, even if I have to type a few more lines to buy that extra safety...</description>
		<content:encoded><![CDATA[<p>I&#8217;ve spent far more hours than I want to think about debugging stack corruption resulting from incorrect casts of function pointers and pointers-to-members.</p>
<p>I&#8217;m currently porting Win32/MFC code (in my Windows-bound day job) from Visual C++ 6.0 to Visual Studio 2005. This problem is particularly insidious with MFC&#8217;s message map macros of old which are full of yummy (and decidedly dodgy) casting.</p>
<p>Making assumptions about function prototypes, calling conventions, return types at the C level is always a bad idea.</p>
<p>Apple provides a solution with NSInvocation and it even lets you check the size of the return type against your expectations, so I&#8217;d prefer to go with that, even if I have to type a few more lines to buy that extra safety&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Shawn Erickson</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83745</link>
		<dc:creator>Shawn Erickson</dc:creator>
		<pubDate>Sat, 14 Apr 2007 17:17:19 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83745</guid>
		<description>Quick example that uses NSInvocation that supports an arbitrary selector to be used... &lt;a href="http://homepage.mac.com/shawnce/ftsw/DynamicSelectorExample.m" rel="nofollow"&gt;DynamicSelectorExample.m&lt;/a&gt;

Note many optimizations could be made (cache the invocation object, etc.).</description>
		<content:encoded><![CDATA[<p>Quick example that uses NSInvocation that supports an arbitrary selector to be used&#8230; <a href="http://homepage.mac.com/shawnce/ftsw/DynamicSelectorExample.m" rel="nofollow">DynamicSelectorExample.m</a></p>
<p>Note many optimizations could be made (cache the invocation object, etc.).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jürgen Schweizer</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83712</link>
		<dc:creator>Jürgen Schweizer</dc:creator>
		<pubDate>Sat, 14 Apr 2007 15:40:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83712</guid>
		<description>I agree with the overkill assessment in the case when all of the code is written by the same author. But I was actually thinking of a framework developer. I believe the dynamic approach you outlined above makes the most sense in frameworks where the actual application is not known at the time of development. And if you go with an informal protocol there is always a slight chance of misuse :).</description>
		<content:encoded><![CDATA[<p>I agree with the overkill assessment in the case when all of the code is written by the same author. But I was actually thinking of a framework developer. I believe the dynamic approach you outlined above makes the most sense in frameworks where the actual application is not known at the time of development. And if you go with an informal protocol there is always a slight chance of misuse :).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daniel Jalkut</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83703</link>
		<dc:creator>Daniel Jalkut</dc:creator>
		<pubDate>Sat, 14 Apr 2007 15:19:45 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83703</guid>
		<description>Jürgen - you're not wrong - my code doesn't check. But I think this is a kind of check that can be implemented at the discretion of the coder. Especially if the delegate sender and receiver are both written by the same coder, who is highly unlikely to ever flagrantly return a non-BOOL from a BOOL-returning delegate method :)

Checking the type of the object seems like overkill to me in many cases.</description>
		<content:encoded><![CDATA[<p>Jürgen - you&#8217;re not wrong - my code doesn&#8217;t check. But I think this is a kind of check that can be implemented at the discretion of the coder. Especially if the delegate sender and receiver are both written by the same coder, who is highly unlikely to ever flagrantly return a non-BOOL from a BOOL-returning delegate method :)</p>
<p>Checking the type of the object seems like overkill to me in many cases.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jürgen Schweizer</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83680</link>
		<dc:creator>Jürgen Schweizer</dc:creator>
		<pubDate>Sat, 14 Apr 2007 13:53:39 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83680</guid>
		<description>Daniel, please correct me if I am wrong, but your code does not seem to check, whether the delegate actually returns a BOOL. As an alternative, I suggest to let the delegate return an NSNumber. This way you will be able to dynamically check (-[NSObject isKindOfClass:]) whether you actually get an object of the correct class.</description>
		<content:encoded><![CDATA[<p>Daniel, please correct me if I am wrong, but your code does not seem to check, whether the delegate actually returns a BOOL. As an alternative, I suggest to let the delegate return an NSNumber. This way you will be able to dynamically check (-[NSObject isKindOfClass:]) whether you actually get an object of the correct class.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: cjwl</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83285</link>
		<dc:creator>cjwl</dc:creator>
		<pubDate>Fri, 13 Apr 2007 14:01:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83285</guid>
		<description>I must have been sleeping when performSelector: broke for this situation, thanks for the post. I would avoid objc_msgSend though and to use your example:

[Ed. Note: Code sample cut for formatting and brevity:]
&lt;code&gt;
       BOOL (*MyMagicSender)(id, SEL, id, id)=(BOOL (*)(id, SEL, id, id))[mDelegate methodForSelector:delSelector];

       if(MyMagicSender!=NULL){
		shouldBrew = MyMagicSender(mDelegate, delSelector, self, [brewTimer fireDate]);
	 }
&lt;/code&gt;
If I wanted forwarding to work I'd go with NSInvocation's.</description>
		<content:encoded><![CDATA[<p>I must have been sleeping when performSelector: broke for this situation, thanks for the post. I would avoid objc_msgSend though and to use your example:</p>
<p>[Ed. Note: Code sample cut for formatting and brevity:]<br />
<code><br />
       BOOL (*MyMagicSender)(id, SEL, id, id)=(BOOL (*)(id, SEL, id, id))[mDelegate methodForSelector:delSelector];</p>
<p>       if(MyMagicSender!=NULL){<br />
		shouldBrew = MyMagicSender(mDelegate, delSelector, self, [brewTimer fireDate]);<br />
	 }<br />
</code><br />
If I wanted forwarding to work I&#8217;d go with NSInvocation&#8217;s.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daniel Jalkut</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83281</link>
		<dc:creator>Daniel Jalkut</dc:creator>
		<pubDate>Fri, 13 Apr 2007 13:41:22 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83281</guid>
		<description>Eric: As usual, I suffer from "in one ear, out the other" syndrome until the day I actually need it :) The documentation you refer to is both good and concise. Nice work!

Todd: the category method is probably a good idea, or at least an instance method encapsulating the "ask delegate for answer." But in any case the example I pasted here is both contrived and poorly documented - only intended to be a bare summary of how you might achieve a goal, given a requirement.</description>
		<content:encoded><![CDATA[<p>Eric: As usual, I suffer from &#8220;in one ear, out the other&#8221; syndrome until the day I actually need it :) The documentation you refer to is both good and concise. Nice work!</p>
<p>Todd: the category method is probably a good idea, or at least an instance method encapsulating the &#8220;ask delegate for answer.&#8221; But in any case the example I pasted here is both contrived and poorly documented - only intended to be a bare summary of how you might achieve a goal, given a requirement.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Todd Ransom</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83263</link>
		<dc:creator>Todd Ransom</dc:creator>
		<pubDate>Fri, 13 Apr 2007 13:14:07 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83263</guid>
		<description>I would avoid using this solution if at all possible because it is not obvious what that line of code does at a glance. A year or three from now when you or a colleague go back to look at this method, will you know the purpose of that line? Sure, you can add comments to it, but I would much rather create a category and implement -(BOOL)performBoolSelector:withObject:withObject: as Lucas suggests, because it looks and feels like Cocoa code instead of some gcc appeasement voodoo.

.02,
Todd</description>
		<content:encoded><![CDATA[<p>I would avoid using this solution if at all possible because it is not obvious what that line of code does at a glance. A year or three from now when you or a colleague go back to look at this method, will you know the purpose of that line? Sure, you can add comments to it, but I would much rather create a category and implement -(BOOL)performBoolSelector:withObject:withObject: as Lucas suggests, because it looks and feels like Cocoa code instead of some gcc appeasement voodoo.</p>
<p>.02,<br />
Todd</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Viuto</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83227</link>
		<dc:creator>Viuto</dc:creator>
		<pubDate>Fri, 13 Apr 2007 11:12:44 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83227</guid>
		<description>... and sometimes you may also need to use gcc's -mstackrealign flag to avoid Intel x86 issues ...

http://0xced.blogspot.com/2006/06/using-gnu-lightning-on-intel-mac.html</description>
		<content:encoded><![CDATA[<p>&#8230; and sometimes you may also need to use gcc&#8217;s -mstackrealign flag to avoid Intel x86 issues &#8230;</p>
<p><a href="http://0xced.blogspot.com/2006/06/using-gnu-lightning-on-intel-mac.html" rel="nofollow">http://0xced.blogspot.com/2006/06/using-gnu-lightning-on-intel-mac.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Eric Albert</title>
		<link>http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187</link>
		<dc:creator>Eric Albert</dc:creator>
		<pubDate>Fri, 13 Apr 2007 08:15:55 +0000</pubDate>
		<guid isPermaLink="false">http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187</guid>
		<description>A couple points here....

First, as with most differences between PowerPC and Intel Macs, this is covered in the Universal Binary Programming Guidelines (and has been since the Intel announcement).  See &lt;a href="http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html" rel="nofollow"&gt;Objective-C Runtime: Sending Messages&lt;/a&gt;, which happens to include this specific example.  I helped write this section and made sure it got included in the document, so I take a little bit of pride in it. :)

Second, Jonathan Johnson's comment about why this behaves differently on the two architectures is close but not quite right.  The C99 'bool' type is a different size on PowerPC and Intel -- four bytes on PowerPC and one byte on Intel -- but the Objective-C BOOL type is the same size on both.  You can see this in objc.h, where BOOL is typedef'd to a signed char.

Why, then, does this sometimes behave differently on PowerPC and Intel?  On PowerPC, the fastest way for the callee to write a one-byte value to the return register (r3) is to fill the entire register, so the compiler always ends up setting the four bytes in r3 to 0x0 or 0x1.  If the caller thinks all four bytes were written, the result is the same.  On Intel, the fastest way for the callee to write a one-byte value to EAX is sometimes to write the full register, as on PowerPC.  Those cases behave the same they do on PowerPC.  But sometimes the compiler decides to use one of the instructions which writes to AX (the low two bytes) or AL (the low byte) instead.  From the compiler's perspective that's legal because it's writing out the return value for a function which is declared to return a single byte...but a caller which think it's getting four bytes back and reads those four bytes will end up seeing garbage in the high two or three bytes.  That's when you realize you need a function pointer, since the function pointer tells the compiler that it's calling a function which is only guaranteed to set one byte in the return value.</description>
		<content:encoded><![CDATA[<p>A couple points here&#8230;.</p>
<p>First, as with most differences between PowerPC and Intel Macs, this is covered in the Universal Binary Programming Guidelines (and has been since the Intel announcement).  See <a href="http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html" rel="nofollow">Objective-C Runtime: Sending Messages</a>, which happens to include this specific example.  I helped write this section and made sure it got included in the document, so I take a little bit of pride in it. :)</p>
<p>Second, Jonathan Johnson&#8217;s comment about why this behaves differently on the two architectures is close but not quite right.  The C99 &#8216;bool&#8217; type is a different size on PowerPC and Intel &#8212; four bytes on PowerPC and one byte on Intel &#8212; but the Objective-C BOOL type is the same size on both.  You can see this in objc.h, where BOOL is typedef&#8217;d to a signed char.</p>
<p>Why, then, does this sometimes behave differently on PowerPC and Intel?  On PowerPC, the fastest way for the callee to write a one-byte value to the return register (r3) is to fill the entire register, so the compiler always ends up setting the four bytes in r3 to 0&#215;0 or 0&#215;1.  If the caller thinks all four bytes were written, the result is the same.  On Intel, the fastest way for the callee to write a one-byte value to EAX is sometimes to write the full register, as on PowerPC.  Those cases behave the same they do on PowerPC.  But sometimes the compiler decides to use one of the instructions which writes to AX (the low two bytes) or AL (the low byte) instead.  From the compiler&#8217;s perspective that&#8217;s legal because it&#8217;s writing out the return value for a function which is declared to return a single byte&#8230;but a caller which think it&#8217;s getting four bytes back and reads those four bytes will end up seeing garbage in the high two or three bytes.  That&#8217;s when you realize you need a function pointer, since the function pointer tells the compiler that it&#8217;s calling a function which is only guaranteed to set one byte in the return value.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.238 seconds -->
