2012-07-19 36 views

回答

6

對於任何最近版本的Clang,這確實是可能的。

Apple ABI for Blocks是私有的,但也是published。由於該文件告訴我們編譯器將用於Block對象的佈局,因此我們可以將這些信息複製到頭文件中並使用它來訪問塊的組件。

Mike Ash的MABlockForwarding project就是這麼做的(參見article) - 這個文件頂部的大部分內容都是來自ABI文檔的複製粘貼。他創建了我們感興趣的東西是BlockSig()功能:

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]; 
} 

將返回(對於有它(他們都與最近鐺做)塊),一個type encoding string描述塊的迴歸和論證類型。從那裏,你可以創建一個NSMethodSignature對象,並請它替其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]; 

結果有3,因爲它包含了塊本身隱藏的參數(和塊不使用隱藏_cmd或者它會是4)。

+0

謝謝Josh(當然還有Mike Ash)!我集成了幾行Mike的代碼來擴展我的斷言工具,它的工作原理!真棒 – Lio 2012-07-19 23:31:16

1

答案是你不能。見邁克灰的頁面上對此評論:

Search for Intropectionsends you here

那麼,什麼是你真正的問題?如果你正確地構造參數,你可以確保你的系統正常工作。例如,你可以做C++用參數的默認值做的事情,並且將每個塊轉換爲一個類型,該類型需要最大數量的參數,並且總是將多個項目推送到堆棧上。或者,您始終可以將第一個參數作爲您在堆棧上推送的參數的數量。如果你推送對象而不是數字/指針,那麼你可以查看每個參數的類並動態適應。

相關問題