【问题标题】:How to implement an IMP function that returns a large struct type determined at run-time?如何实现返回运行时确定的大型结构类型的 IMP 函数?
【发布时间】:2011-07-25 12:15:34
【问题描述】:

背景:CamelBones 将 Perl 类注册到 Objective-C 运行时。 为此,每个 Perl 方法都使用相同的 IMP 注册 功能;该函数检查其 self_cmd 参数以查找 调用哪个 Perl 方法。

这几年来一直运行良好,对于那些 与objc_msgSend一起发送。但现在我想添加对 从 Perl 方法返回浮点和大型结构类型。 浮点并不难;我将简单地编写另一个返回的 IMP double,用于处理使用objc_msgSend_fpret 发送的消息。

问题是如何处理objc_msgSend_stret。写一个 为每个可能的结构返回类型单独的 IMP 是不切实际的,因为 两个原因:首先,因为即使我这样做只是为了结构类型 在编译时已知的,这是一个荒谬的函数数量。 其次,因为我们讨论的是一个可以链接到任意 Objective-C 和 Perl 代码的框架,所以在编译框架时我们知道所有潜在的结构类型。

我希望做的是写一个可以处理任何返回的IMP 通过objc_msgSend_stret 发送的类型。我可以把它写成 返回void,并将指针参数指向返回缓冲区,例如 旧的objc_msgSend_stret 被宣布了吗?即使那件事发生在 现在工作,我可以依靠它在未来继续工作吗?

感谢您的任何建议 - 我一直在为此绞尽脑汁。 :-)

更新:

这是我从 Apple 的一位运行时工程师那里收到的建议,在他们的 objc 语言邮件列表中:

你必须编写汇编代码来处理 这种情况。

您的建议在某些方面失败了 架构,其中 ABI 表示“功能 用指向 a 的指针返回 void struct 作为第一个参数”不同 来自“函数返回结构”。 (在 i386 上,结构地址被弹出 调用者从堆栈中合二为一 案例和被调用者在另一个 案例。)这就是为什么原型 objc_msgSend_stret 已更改。

汇编代码将捕获 struct返回地址,偷运进去 非结构返回 C 函数调用 在不打扰其他人的情况下 参数,然后做正确的 退出时特定于 ABI 的清理 (ret $4 在 i386 上)。或者,大会 代码可以捕获所有 参数。转运机械 做这样的事情。那个代码 可能在开源 CoreFoundation 如果你想看看有什么技巧 看起来像。

我将保留这个问题,以防有人集思广益,但这个问题直接来自 Apple 自己的“运行时管理员”,我认为这可能是我可能得到的最权威的答案。是时候清理 x86 参考手册的灰尘,把我的汇编器上的锈都敲掉了,我猜...

【问题讨论】:

  • 我看不出你为什么不能在未来依赖void-return 和缓冲的做事方式。 objc_msgSend_stret 不会很快消失,只要你为缓冲区分配足够的内存,我认为你应该没问题。但这肯定不是最优雅的解决方案。
  • 见上文。似乎简单的方法不可靠。哦,好吧,或多或少符合我的预期。
  • @Sherm 唉!不过很高兴知道。
  • 天哪,说老了。当我看到 IMP 时,我立刻想到了en.wikipedia.org/wiki/Interface_Message_Processor。啊,该死的……我要去喝杯啤酒。
  • 也许你应该用苹果工程师的信息来回答你的问题。

标签: objective-c perl objective-c-runtime


【解决方案1】:

看来苹果工程师是对的:唯一的出路就是汇编代码。以下是一些有用的入门指南:

  • 来自 Objective-C 运行时代码:The i386x86_64 为各种消息传递方法手工制作的信使程序集存根。
  • An SO answer 提供调度的概述。
  • A in-depth review 的调度机制,对汇编代码进行逐行分析

希望对你有帮助。

【讨论】:

  • 谢谢,但是如何使用 objc_msgSend* 发送消息不是我问的问题。多年来,我已经掌握了这部分。 :-)
  • 对不起,我的错。我以错误的方式解决了这个问题。我已经更新了我的答案。
  • 对不起,但这仍然不是我想要的。我知道如何发送消息。这不是我要问的。恭喜你的赏金。 :-)
  • 我的答案是指向苹果工程师描述的转发机制,即如何将消息发送到 IMP。我认为它可能有用... :-(
猜你喜欢
  • 2011-01-10
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
  • 2016-10-18
  • 2021-12-24
相关资源
最近更新 更多