Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to implement an IMP function that returns a large struct type determined at run-time?
    text
    copied!<p>Background: CamelBones registers Perl classes with the Objective-C runtime. To do this, every Perl method is registered with the same IMP function; that function examines its <code>self</code> &amp; <code>_cmd</code> arguments to find which Perl method to call.</p> <p>This has worked well enough for several years, for messages that were dispatched with <code>objc_msgSend</code>. But now I want to add support for returning floating-point and large struct types from Perl methods. Floating-point isn't hard; I'll simply write another IMP that returns double, to handle messages dispatched with <code>objc_msgSend_fpret</code>.</p> <p>The question is what to do about <code>objc_msgSend_stret</code>. Writing a separate <code>IMP</code> for every possible struct return type is impractical, for two reasons: First, because even if I did so only for struct types that are known at compile-time, that's an absurd number of functions. And second, because we're talking about a framework that can be linked against any arbitrary Objective-C &amp; Perl code, we <em>don't</em> know all the potential struct types when the framework is being compiled.</p> <p>What I hope to do is write a single <code>IMP</code> that can handle any return type that's dispatched via <code>objc_msgSend_stret</code>. Could I write it as returning <code>void</code>, and taking a pointer argument to a return buffer, like the old <code>objc_msgSend_stret</code> was declared? Even if that happened to work for now, could I rely on it continuing to work in the future?</p> <p>Thanks for any advice - I've been racking my brain on this one. :-)</p> <p><strong>Update:</strong></p> <p>Here's the advice I received from one of Apple's runtime engineers, on their objc-language mailing list:</p> <blockquote> <p>You must write assembly code to handle this case.</p> <p>Your suggestion fails on some architectures, where ABI for "function returning void with a pointer to a struct as the first argument" differs from "function returning a struct". (On i386, the struct address is popped from the stack by the caller in one case and by the callee in the other case.) That's why the prototype for <code>objc_msgSend_stret</code> was changed.</p> <p>The assembly code would capture the struct return address, smuggle it into non-struct-return C function call without disturbing the rest of the parameters, and then do the right ABI-specific cleanup on exit (<code>ret $4</code> on i386). Alternatively, the assembly code can capture all of the parameters. The forwarding machinery does something like this. That code might be in open-source CoreFoundation if you want to see what the techniques look like.</p> </blockquote> <p>I'll leave this question open, in case someone brainstorms a better idea, but with this coming directly from Apple's own "runtime wrangler," I figure it's probably as authoritative an answer as I'm likely to get. Time to dust off the x86 reference manuals and knock the rust off my assembler-fu, I guess...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload