首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSInvocation需要NSMethodSignature

NSInvocation需要NSMethodSignature
EN

Stack Overflow用户
提问于 2013-09-05 23:33:17
回答 2查看 489关注 0票数 0

有几天我一直在想,NSInvocation是否需要NSMethodSignature。假设我们想编写自己的NSInvocation,我的要求是这样的:

  1. 我需要一个选择器SEL
  2. 要调用选择器的目标对象。
  3. 参数数组

然后,我将从目标和SEL中取出SEL,并将argument作为参数传递。

所以,我的问题是,为什么我们需要一个NSMethodSignature来构造和使用一个NSInvocation

注意:我确实知道,只有一个SEL和一个目标,我们没有这个方法的参数和返回类型,但是为什么我们会关心args和返回的类型呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-06 08:37:01

C中的每种类型都有不同的大小。(即使是相同的类型,在不同的系统上也可以有不同的大小,但现在我们将忽略这一点。)根据系统的不同,int可以有32位或64位。double需要64位。char代表8位(但根据系统的传递约定,它可以作为常规的int传递)。最后也是最重要的一点是,struct类型有不同的大小,这取决于它中有多少个元素以及它们的每个大小;它可以有多大并不一定。因此,无论类型如何,都不可能以相同的方式传递参数。因此,调用函数如何安排参数,以及被调用函数如何解释其参数,必须取决于函数的签名。(不能使用与类型无关的“参数数组”;数组元素的大小是多少?)在编译正常函数调用时,编译器在编译时就知道签名,并且可以根据调用约定正确地排列签名。但是NSInvocation用于在运行时管理调用。因此,它需要方法签名的表示才能工作。

NSInvocation可以做几件事。每一件事都需要了解参数的数量和类型(至少类型的大小):

  1. 当消息被发送到一个没有方法的对象时,运行时将构造一个NSInvocation对象并将其传递给-forwardInvocation:NSInvocation对象包含传递的所有参数的副本,因为以后可以存储和调用它。因此,运行库至少需要知道参数总共有多大,以便将寄存器和/或堆栈中的正确数据量(取决于调用约定中参数的排列方式)复制到NSInvocation对象中。
  2. 当您有一个NSInvocation对象时,可以使用-getArgument:atIndex:查询I‘’th参数的值。还可以使用-setArgument:atIndex:设置/更改I‘’th参数的值。这要求它知道1)在其数据缓冲区中I‘’th参数从哪里开始;这需要知道以前的参数有多大,以及2) I‘’th参数有多大,这样它就可以复制正确的数据量(如果它复制得太少,它将有一个损坏的值;如果它复制太多,比如,当您执行getArgument时,它可以覆盖您给它的缓冲区;或者当您执行setArgument时,覆盖其他参数)。
  3. 您可以让它执行-retainArguments,这将使它保留所有对象指针类型的参数。这要求它区分对象指针类型和其他类型,因此类型信息必须不仅包括大小。
  4. 您可以调用NSInvocation,这将导致它构造和执行对方法的调用。这至少要求它知道要将多少数据从其缓冲区复制到寄存器/堆栈中,以便将所有数据放在函数所期望的位置。这至少需要知道所有参数的组合大小,而且可能还需要知道各个参数的大小,以便正确地计算寄存器上的参数和堆栈上的参数之间的界限。
  5. 您可以使用-getReturnValue:获得调用的返回值;这与获取上面的参数有类似的问题。

代码语言:javascript
复制
- A thing not mentioned above is that the return type may also have a great effect on the calling mechanism. On x86 and ARM, the common architectures for Objective-C, when the return type is a `struct` type, the calling convention is very different -- effectively an additional (first) parameter is added before all the regular parameters, which is a pointer to the space that the struct result should be written. This is instead of the regular calling convention where the result is returned in a register. (In PowerPC I believe that `double` return type is also treated specially.) So knowing the return type is essentially for constructing and invoking the `NSInvocation`.

票数 3
EN

Stack Overflow用户

发布于 2013-09-06 00:56:29

消息发送和转发机制需要NSMethodSignature才能在调用中正常工作。NSMethodSignature和NSInvocation是围绕__builtin_call()构建的一个包装器,它既依赖于体系结构,又对给定函数所需的堆栈空间非常保守。因此,当调用调用时,__builtin_call()从方法签名中获取它所需的所有信息,并且可以通过向转发机制抛出调用来优雅地失败,因为它也接收到了关于堆栈应该如何查找重新调用的正确信息。

尽管如此,如果不修改C语言以支持将数组转换为VARARGS,则无法生成一个没有方法签名的原始NSInvocation,因为objc_msgSend()及其表亲不允许它。即使您能够解决这个问题,您也需要计算参数的大小和返回类型(不太难,但如果您错了,那么您就大错特错了),并管理对__builtin_call()的适当调用,这将需要对消息发送体系结构或ffi有一个非常熟悉的知识(不管怎么说,后者可能会下降到__builtin_call() )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18647581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档