背景:CamelBones 向 Objective-C 运行时注册 Perl 类。为此,每个 Perl 方法都注册了相同的 IMP 函数;该函数检查其self
&_cmd
参数以找到要调用的 Perl 方法。
对于使用objc_msgSend
. 但现在我想添加对从 Perl 方法返回浮点和大型结构类型的支持。浮点并不难;我将简单地编写另一个返回 double 的 IMP 来处理以objc_msgSend_fpret
.
问题是该怎么办objc_msgSend_stret
。为每个可能的结构返回类型单独编写一个IMP
是不切实际的,原因有两个:首先,因为即使我只为在编译时已知的结构类型这样做,这也是一个荒谬的函数数量。其次,因为我们讨论的是一个可以链接到任意 Objective-C 和 Perl 代码的框架,所以在编译框架时我们不知道所有潜在的结构类型。
我希望做的是编写一个IMP
可以处理任何通过objc_msgSend_stret
. 我可以将它写为返回void
,并将指针参数传递给返回缓冲区,就像objc_msgSend_stret
声明旧的一样?即使这碰巧现在有效,我可以依靠它在未来继续工作吗?
感谢您的任何建议-我一直在为此绞尽脑汁。:-)
更新:
这是我从 Apple 的一位运行时工程师那里收到的建议,在他们的 objc 语言邮件列表中:
您必须编写汇编代码来处理这种情况。
您的建议在某些架构上失败,其中“函数返回 void 并以指向结构的指针作为第一个参数”的 ABI 与“函数返回结构”不同。(在 i386 上,结构地址在一种情况下由调用者从堆栈中弹出,在另一种情况下由被调用者从堆栈中弹出。)这就是
objc_msgSend_stret
更改原型的原因。汇编代码将捕获结构返回地址,将其偷运到非结构返回 C 函数调用中,而不会干扰其余参数,然后在退出时(
ret $4
在 i386 上)进行正确的 ABI 特定清理。或者,汇编代码可以捕获所有参数。转发机器会做这样的事情。如果您想了解这些技术是什么样子,那么该代码可能位于开源 CoreFoundation 中。
我会留下这个问题,以防有人集思广益,但这个问题直接来自苹果自己的“运行时牧马人”,我认为这可能是我可能得到的最权威的答案。是时候清理 x86 参考手册的灰尘并敲掉我的汇编器上的锈迹了,我猜...