【问题标题】:Can Foundation tell me whether an Objective-C method requires a special structure return?Foundation 能告诉我一个 Objective-C 方法是否需要特殊的结构返回吗?
【发布时间】:2013-08-09 09:33:37
【问题描述】:

我理解的背景:Objective-C 方法调用基本上是一个带有两个隐藏参数(接收器和选择器)的 C 函数调用。 Objective-C 运行时包含一个名为 objc_msgSend() 的函数,它允许以这种方式调用方法。不幸的是,当函数返回结构时,可能需要进行一些特殊处理。有一些神秘的(有些人可能会说是疯狂的)规则来控制结构是否像其他值一样返回,或者它是否实际上是通过隐藏的第一个参数中的引用返回的。对于 Objective-C,在这些情况下必须使用另一个名为 objc_msgSend_stret() 的函数。

问题:给定一个方法,NSMethodSignature 或其他东西可以告诉我是否必须使用 objc_msgSend() 或 objc_msgSend_stret()?到目前为止,我们发现 NSMethodSignature 知道这一点,它会在其调试输出中打印出来,但似乎没有公共 API。

如果你想回答“你到底为什么要那样做?!”,请在做之前阅读以下内容:https://github.com/erikdoe/ocmock/pull/41

【问题讨论】:

  • 大约两周前我也试图弄清楚这一点,但也找不到比您在该 GitHub 线程中包含的更多信息。在其他地方,我看到 Greg Parker 提出了“经验方法”:针对您关心的任何架构编译一些示例,并检查结果。我现在正在尝试确定 libclang 是否会在这里提供帮助。

标签: objective-c objective-c-runtime


【解决方案1】:

Objective-C 在给定架构上为 C 使用相同的底层 ABI,因为方法只是带有隐式 self_cmd 参数的 C 函数。

换句话说,如果你有一个方法:

- (SomeStructType)myMeth:(SomeArgType)arg;

那么这真的是一个普通的 C 函数:

SomeStructType myMeth(id self, SEL _cmd, SomeArgType arg);

我很确定您已经知道这一点,但我只是为其他读者提一下。 换句话说,您想询问 libffi 或任何类型的类似库如何为该架构返回 SomeStructType

【讨论】:

    【解决方案2】:

    NSMethodSignature 有一个-methodReturnType,您可以检查它以查看返回类型是否为struct。这是你想要做的吗?

    【讨论】:

    • 它确实告诉我返回类型是否是一个结构,但它没有告诉我该结构是在寄存器中返回还是通过堆栈上的 ref 返回。所以,我还是不知道是非得用objc_msgSend还是objc_msgSend_stret。
    • 我明白了。那么这超出了我的知识范围
    【解决方案3】:

    来自http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html

    结构类型在寄存器中返回的规则总是 神秘的,有时是疯狂的。 ppc32 很简单:结构永远不会返回 寄存器。 i386 很简单:sizeof 完全相等的结构 到 1、2、4 或 8 在寄存器中返回。 x86_64 比较复杂, 包括在 FPU 中返回浮点结构字段的规则 寄存器,ppc64 的规则和例外会让你头晕目眩。 血淋淋的细节记录在 Mac OS X ABI 指南中,尽管作为 通常,如果文档和编译器不同意,那么 文档有误。

    如果你直接调用 objc_msgSend 并且需要知道是否 对特定的结构类型使用 objc_msgSend_stret,我推荐 经验方法:编写一行代码调用你的方法, 在您关心的每个架构上编译它,然后查看 汇编代码以查看编译器使用哪个调度函数。

    【讨论】:

      猜你喜欢
      • 2013-06-13
      • 2012-12-16
      • 2011-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多