Block的運行時實現筆記

原來簡書默認的編輯器是富文本,必須從設置里手動切換成MarkDown才能使用···
真是坑···

下面是一個簡單的block使用場景:

int main()
{
  void (^blk) (void) = ^{ printf("Block\n"); };
  blk();
  return 0;
}

使用clang -rewrite-objc轉換成C/C++代碼:

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

struct __main_block_impl_0 {
  struct __block_impl impl; //注意此處不是結構體指針,而是拷貝結構體
  struct __main_block_desc_0 *Desc;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags = 0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) 
{
  printf("Block\n");
}

static struct __main_block_desc_0 {
  unsigned long reserved;
  unsigned long Block_size;
} __main_block_desc_0_DATA = {
  0,
  sizeof(struct __main_block_impl_0)
};

int main() {
  //調用block構造函數初始化block的結構體并聲明賦值結構體指針
  void (*blk) (void) = (void (*) (void)) &__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA);
  //調用內部函數指針執行匿名函數的實現
  ((void (*) (struct __block_impl *))((struct __block_impl *)blk)->FuncPtr)((struct __block_impl *)blk);
  return 0;
}

可以看出通過Block使用的匿名函數實際上被作為簡單的C語言函數來處理,匿名函數默認傳入了一個struct __main_block_impl_0類型的結構體指針__cself,此處匿名函數僅僅是調用了printf打印一個寫好的字符串;但如果該block有截獲變量的瞬時值,這些瞬時值會被保存為block的struct __main_block_impl_0類型的結構體中作為成員變量,匿名函數被調用時通過傳入的__cself指針來訪問并使用這些成員變量的值。

如果上述main()函數中增加變量聲明int val = 10;,并且block中的打印函數改成printf(val);,那么對應的struct __main_block_impl_0結構體會變成:

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0 *Desc;
  int val;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags = 0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }
};

而對應的函數實現會變成:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int val = __cself->val;
  printf(val);
}

這就是為什么block捕獲的是自己被初始化時外部變量的瞬時值,而不受這些變量改變的影響。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容