Objective-C block實現程式碼分析

來源:互聯網
上載者:User

標籤:

block內部結構

讓我們寫一個block

void exampleBlock() {    // NSConcreteStackBlock    int a = 1;    __block int b = 2;    int(^blockTest0)(int c) = ^(int c){        return a + b + c;    };    int c = 3;    blockTest0(c);    // NSConcreteGlobalBlock    void(^blockTest2)(void) = ^(void){        ;    };    blockTest2();}

用clang轉成c分析下

clang -rewrite-objc block.c

能夠看到他們的定義是

struct __exampleBlock_block_impl_0 {  struct __block_impl impl;  struct __exampleBlock_block_desc_0* Desc;  int a;  __Block_byref_b_0 *b; // by ref  __exampleBlock_block_impl_0(void *fp, struct __exampleBlock_block_desc_0 *desc, int _a, __Block_byref_b_0 *_b, int flags=0) : a(_a), b(_b->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};// __block_implstruct __block_impl {  void *isa;  int Flags;  int Reserved;  void *FuncPtr;};// __exampleBlock_block_desc_0struct __exampleBlock_block_impl_0 {  struct __block_impl impl;  struct __exampleBlock_block_desc_0* Desc;  int a;  __Block_byref_b_0 *b; // by ref  __exampleBlock_block_impl_0(void *fp, struct __exampleBlock_block_desc_0 *desc, int _a, __Block_byref_b_0 *_b, int flags=0) : a(_a), b(_b->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};// __exampleBlock_block_impl_2struct __exampleBlock_block_impl_2 {  struct __block_impl impl;  struct __exampleBlock_block_desc_2* Desc;  __exampleBlock_block_impl_2(void *fp, struct __exampleBlock_block_desc_2 *desc, int flags=0) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};

初始化和運行代碼

void exampleBlock() {    // blockTest0    int a = 1;    __attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 2};    int(*blockTest0)(int c) = (int (*)(int))&__exampleBlock_block_impl_0((void *)__exampleBlock_block_func_0, &__exampleBlock_block_desc_0_DATA, a, (__Block_byref_b_0 *)&b, 570425344);    int c = 3;    ((int (*)(__block_impl *, int))((__block_impl *)blockTest0)->FuncPtr)((__block_impl *)blockTest0, c);    // blockTest2    void(*blockTest2)(void) = (void (*)())&__exampleBlock_block_impl_2((void *)__exampleBlock_block_func_2, &__exampleBlock_block_desc_2_DATA);    ((void (*)(__block_impl *))((__block_impl *)blockTest2)->FuncPtr)((__block_impl *)blockTest2);}

我們先看看blockTest2,它是由 結構體impl, 結構體Desc, 構造方法__exampleBlock_block_impl_2() 組成展開後是

  • *isa 指向該執行個體對象(代碼裡是NSConcreteStackBlock,事實上應該是NSConcreteGlobalBlock)
  • Flags 用於按bit位表示一些block的附加資訊
  • reserved 保留變數
  • *FuncPtr 函數指標,指向詳細的block實現的函數調用地址(代碼裡是__exampleBlock_block_func_2)
static void __exampleBlock_block_func_2(struct __exampleBlock_block_impl_2 *__cself) {        ;}
  • size_t reserved 這個傳進來的是0
  • Block_size 結構體的大小
static struct __exampleBlock_block_desc_2 {  size_t reserved;  size_t Block_size;} __exampleBlock_block_desc_2_DATA = { 0, sizeof(struct __exampleBlock_block_impl_2)};

然後我們在看blockTest,它比blockTest2多了2個變數a, b

  • int a; 外部變數a,

  • Block_byref_b_0 *b; 加了block修飾的b, 傳的是 Block_byref_b_0

在產生的初始化代碼中則多了3個傳入值

    int(*blockTest0)(int c) = (int (*)(int))&__exampleBlock_block_impl_0((void *)__exampleBlock_block_func_0, &__exampleBlock_block_desc_0_DATA, a, (__Block_byref_b_0 *)&b, 570425344);
  • a是這個是直接傳值進去,然後被複製給 a

  • b是傳的地址, 是把 __Block_byref_b_0 賦值給 b

__Block_byref_b_0這個結構體是

struct __Block_byref_b_0 {  void *__isa;__Block_byref_b_0 *__forwarding; int __flags; int __size; int b;};

__forwarding 是一個指向自己的指標.

__Block_byref_b_0 的初始化代碼例如以下:

__attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 2};

我們能夠看出a是直接複製進去的,b是被轉到了一個結構體裡,然後吧這個結構體的指標傳進去,所以block不能改動a,能改動b.

  • 570425344 這個應該是傳給Flags

blockTest0的Desc和blockTest2也有所不同,展開後是

static struct __exampleBlock_block_desc_0 {  size_t reserved;  size_t Block_size;  void (*copy)(struct __exampleBlock_block_impl_0*, struct __exampleBlock_block_impl_0*);  void (*dispose)(struct __exampleBlock_block_impl_0*);} __exampleBlock_block_desc_0_DATA = { 0, sizeof(struct __exampleBlock_block_impl_0), __exampleBlock_block_copy_0, __exampleBlock_block_dispose_0};

多了2個函數指標copy, dispose,對於在調用前後改動對應變數的引用計數, 分別指向

static void __exampleBlock_block_copy_0(struct __exampleBlock_block_impl_0*dst, struct __exampleBlock_block_impl_0*src) {_Block_object_assign((void*)&dst->b, (void*)src->b, 8/*BLOCK_FIELD_IS_BYREF*/);}static void __exampleBlock_block_dispose_0(struct __exampleBlock_block_impl_0*src) {_Block_object_dispose((void*)src->b, 8/*BLOCK_FIELD_IS_BYREF*/);}

再來看下blockTest0的*FuncPtr

 static int __exampleBlock_block_func_0(struct __exampleBlock_block_impl_0 *__cself, int c) {  __Block_byref_b_0 *b = __cself->b; // bound by ref  int a = __cself->a; // bound by copy        return a + (b->__forwarding->b) + c;    }

如可以看到的a使用輸入的副本a, b使用一種結構,其中b

著作權聲明:本文博主原創文章。部落格,未經同意不得轉載。

Objective-C block實現程式碼分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.