Find out how many arguments a block needs

Say I have an array containing blocks, and I need to claim that they all expect a given number of arguments.

Is there any way to find this programmatically?

+4
source share
2 answers

This is really possible for any recent version of Clang.

Apple ABI for blocks is private, but also published . Since this document tells us the layout that the compiler will use for the Block object, we can duplicate this information in the header file and use it to access the components of the block.

Mike Ash The MABlockForwarding project does just that (see also the article ) - most of the material at the top of this file is a copy in an ABI document. What he created, in which we are interested, is the BlockSig() function:

 static const char *BlockSig(id blockObj) { struct Block *block = (__bridge void *)blockObj; struct BlockDescriptor *descriptor = block->descriptor; assert(block->flags & BLOCK_HAS_SIGNATURE); int index = 0; if(block->flags & BLOCK_HAS_COPY_DISPOSE) index += 2; return descriptor->rest[index]; } 

which will be returned (for blocks that have it (which they all do with the recent Clang)), enter an encoding string describing the block return and argument types. From there, you can create an NSMethodSignature object and request its numberOfArguments :

  NSString * (^block)(int, NSArray *) = ^NSString * (int i, NSArray * a){ return @"Oh, yeah!"; }; const char * types = BlockSig(block); NSMethodSignature * sig = [NSMethodSignature signatureWithObjCTypes:types]; [sig numberOfArguments]; 

The result is 3 because it contains a hidden argument for the block itself (and the blocks do not use the hidden argument _cmd or it will be 4).

+6
source

Answer: you cannot. See Comment on Mike Ashe's page for this:

Search for Intropection that sends you here

So what is your real problem? If you structure arguments correctly, you can ensure that your system functions properly. For example, you can do what C ++ does with the default values ​​for the arguments, and assign each block to a type that takes the maximum number of arguments, and always click on it with a lot of elements on the stack. Or you can always have the first argument in the number of arguments that you push on the stack. If you click objects, not numbers / pointers, then you r-blocks can look at the class of each argument and dynamically adapt.

+1
source

All Articles