I have been wondering for a couple of days if NSInvocation
should need the NSMethodSignature
.
Lets say we want to write our own NSInvocation, my requirements would be as so:
- I need a selector
SEL
- The target object to call the selector on
- The argument array
Then i would get the IMP
out from the target and the SEL
, and pass the argument
as parameters.
So, my question is, why do we need an NSMethodSignature
to construct and use an NSInvocation
?
Note: I do know that by having only a SEL
and a target, we dont have the arguments and return type for this method, but why would we care about the types of the args and returns?
Each type in C has a different size. (Even the same type can have different sizes on different systems, but we'll ignore that for now.)
int
can have 32 or 64 bits, depending on the system.double
takes 64 bits.char
represents 8 bits (but might be passed as a regularint
depending on the system's passing convention). And finally and most importantly,struct
types have various sizes, depending on how many elements are in it and each of their sizes; there is no bound to how big it can be. So it is impossible to pass arguments the same way regardless of type. Therefore, how the calling function arranges the arguments, and how the called function interprets its arguments, must be dependent on the function's signature. (You cannot have a type-agnostic "argument array"; what would be the size of the array elements?) When normal function calls are compiled, the compiler knows the signature at compile time, and can arrange it correctly according to calling convention. ButNSInvocation
is for managing an invocation at runtime. Therefore, it needs a representation of the method signature to work.There are several things that the
NSInvocation
can do. Each of those things requires knowledge of the number and types (at least the sizes of the types) of the parameters:NSInvocation
object and passes it to-forwardInvocation:
. TheNSInvocation
object contains a copy of all the arguments that are passed, since it can be stored and invoked later. Therefore, the runtime needs to know, at the very least, how big the parameters in total are, in order to copy the right amount of data from registers and/or stack (depending on how arguments are arranged in the calling convention) into theNSInvocation
object.NSInvocation
object, you can query for the value of the i'th argument, using-getArgument:atIndex:
. You can also set/change the value for the i'th argument, using-setArgument:atIndex:
. This requires it to know 1) Where in its data buffer the i'th parameter starts; this requires knowing how big the previous parameters are, and 2) how big the i'th parameter is, so that it can copy the right amount of data (if it copies too little, it will have a corrupt value; if it copies too much, say, when you dogetArgument
, it can overwrite the buffer you gave it; or when you dosetArgument
, overwrite other arguments).-retainArguments
, which causes it to retain all arguments of object pointer type. This requires it to distinguish between object pointer types and other types, so the type information must include not only the size.NSInvocation
, which causes it to construct and execute the call to the method. This requires it to know, at the very least, how much data to copy from its buffer into the registers/stack to place all the data where the function will expect it. This requires knowing at least the combined size of all parameters, and probably also needs to know the sizes of individual parameters, so that the divide between parameters on registers and parameters on stack can be figured out correctly.You can get the return value of the call using
-getReturnValue:
; this has similar issues to the getting of arguments above.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 thatdouble
return type is also treated specially.) So knowing the return type is essentially for constructing and invoking theNSInvocation
.