如何实现一个IMP函数,返回在运行时确定的大型结构types?
背景:CamelBones使用Objective-C运行时注册Perl类。 为此,每个Perl方法都使用相同的IMP函数进行注册; 该函数检查它的self
& _cmd
参数来查找要调用的Perl方法。
对于使用objc_msgSend
调度的消息,这已经运行了好几年了。 但是现在我想添加从Perl方法返回浮点和大型结构types的支持。 浮点不难; 我将简单地写另一个返回double的IMP来处理使用objc_msgSend_fpret
分派的消息。
问题是如何处理objc_msgSend_stret
。 为每个可能的结构返回types编写一个单独的IMP
是不切实际的,原因有二:首先,因为即使我只为编译时已知的结构types这样做,这是一个荒谬的数量的函数。 其次,因为我们正在讨论一个可以与任意Objective-C和Perl代码链接的框架,所以在编译框架时,我们并不知道所有可能的结构types。
我希望做的是写一个单一的IMP
,可以处理任何通过objc_msgSend_stret
调度的返回types。 我可以写它作为返回void
,并采取指针参数返回缓冲区,如旧的objc_msgSend_stret
被宣布? 即使这件事现在还在继续,我可以依靠它继续在未来工作吗?
感谢您的任何build议 – 我一直在这个问题上绞尽脑汁。 🙂
更新:
下面是我从苹果的一个运行时间工程师那里得到的关于objc-language邮件列表的build议:
您必须编写汇编代码来处理这种情况。
在某些体系结构中,您的build议失败,其中“返回void作为第一个参数指向结构体的函数”的ABI不同于“函数返回结构体”。 (在i386中,结构地址是由调用者在一种情况下由被调用者popup的,另一种情况是由被调用者popup)。这就是为什么
objc_msgSend_stret
的原型被改变的原因。汇编代码将捕获结构返回地址,走私它到非结构返回C函数调用,而不会干扰其余的参数,然后做退出(i386
ret $4
上正确的ABI特定的清理。 或者,汇编代码可以捕获所有的参数。 转发机器做这样的事情。 如果你想看看这些技术是什么样的话,那么这个代码可能在开源的CoreFoundation中。
我会留下这个问题,以防有人对更好的想法感到头疼,但是直接来自苹果公司自己的“运行时间争吵者”,我认为这可能是一个权威的答案,我可能会得到。 有时间清除x86参考手册,并将我的汇编程序中的锈掉掉,我猜…
看来,苹果工程师是正确的:唯一要走的是汇编代码。 这里有一些有用的指针入门:
- 从Objective-C运行时代码: i386和x86_64手工构build的各种消息传递方法的消息组合存根。
- 提供调度概述的SO答案 。
- 通过对汇编代码的逐行分析深入分析调度机制
希望能帮助到你。