美文网首页iOS Developer
Block学习笔记一之结构探究

Block学习笔记一之结构探究

作者: littlewish | 来源:发表于2017-04-30 21:02 被阅读100次

    Block代码实现探究

    #import "stdio.h"
    
    int main()
    {
        void (^blk)(void) = ^{
          printf("block/n");
        };
    
        blk();
        return 0;
    };
    

    使用clang命令

    clang -rewrite-objc block.m
    

    其中block.m是文件的名字,转换为可读的源代码:block.cpp

    block的本质是结构体,基本定义的源码定义如下:

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

    我们写的

    void (^blk)(void) = ^{
          printf("block/n");
        };
    

    转化成了

    //生成对应的结构体声明
    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) {
         //&_NSConcreteStackBlock block结构体实例
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    //void 是返回类型 __main_block_func_0是函数名称 *__cself是参数 这里相当于self
    // 这个是block里面的方法实现
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    
          printf("block/n");
        }
    
    //根据__main_block_impl_0的大小进行初始化
    static struct __main_block_desc_0 {
      size_t reserved;
      size_t Block_size;
    } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
    

    整个main函数转化为:

    int main()
    {
        //使用__main_block_impl_0的构造函数 生成结构体对象并将指针赋值给blk
        void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        //blk的调用 除去类型转换简化为 
        // (*blk->impl.FuncPtr)(blk);
        ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
        return 0;
    };
    

    Block和Objective-C中类的实现原理基本一致,都是使用结构体。

    下面是一个基于objc_class的class_t的结构体样式。

    struct class_t{
            struct class_t *isa;
            struct class_t *superclass;
            Cache cache;
            IMP *vtable;
            uintptr_t data_NEVER_USE;
    }
    

    Block其实和其他类实现一样,是Objective-C的对象。

    附录

    clang解析的完整代码(有点多)有兴趣的朋友可以按上面的clang命令自己解析看看。

    #ifndef __OBJC2__
    #define __OBJC2__
    #endif
    struct objc_selector; struct objc_class;
    struct __rw_objc_super { 
        struct objc_object *object; 
        struct objc_object *superClass; 
        __rw_objc_super(struct objc_object *o, struct objc_object *s) : object(o), superClass(s) {} 
    };
    #ifndef _REWRITER_typedef_Protocol
    typedef struct objc_object Protocol;
    #define _REWRITER_typedef_Protocol
    #endif
    #define __OBJC_RW_DLLIMPORT extern
    __OBJC_RW_DLLIMPORT void objc_msgSend(void);
    __OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);
    __OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);
    __OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);
    __OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);
    __OBJC_RW_DLLIMPORT struct objc_class *objc_getClass(const char *);
    __OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass(struct objc_class *);
    __OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass(const char *);
    __OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);
    __OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);
    __OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);
    __OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);
    #ifdef _WIN64
    typedef unsigned long long  _WIN_NSUInteger;
    #else
    typedef unsigned int _WIN_NSUInteger;
    #endif
    #ifndef __FASTENUMERATIONSTATE
    struct __objcFastEnumerationState {
        unsigned long state;
        void **itemsPtr;
        unsigned long *mutationsPtr;
        unsigned long extra[5];
    };
    __OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);
    #define __FASTENUMERATIONSTATE
    #endif
    #ifndef __NSCONSTANTSTRINGIMPL
    struct __NSConstantStringImpl {
      int *isa;
      int flags;
      char *str;
    #if _WIN64
      long long length;
    #else
      long length;
    #endif
    };
    #ifdef CF_EXPORT_CONSTANT_STRING
    extern "C" __declspec(dllexport) int __CFConstantStringClassReference[];
    #else
    __OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];
    #endif
    #define __NSCONSTANTSTRINGIMPL
    #endif
    #ifndef BLOCK_IMPL
    #define BLOCK_IMPL
    struct __block_impl {
      void *isa;
      int Flags;
      int Reserved;
      void *FuncPtr;
    };
    // Runtime copy/destroy helper functions (from Block_private.h)
    #ifdef __OBJC_EXPORT_BLOCKS
    extern "C" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);
    extern "C" __declspec(dllexport) void _Block_object_dispose(const void *, const int);
    extern "C" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];
    extern "C" __declspec(dllexport) void *_NSConcreteStackBlock[32];
    #else
    __OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);
    __OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);
    __OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];
    __OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];
    #endif
    #endif
    #define __block
    #define __weak
    
    #include <stdarg.h>
    struct __NSContainer_literal {
      void * *arr;
      __NSContainer_literal (unsigned int count, ...) {
        va_list marker;
        va_start(marker, count);
        arr = new void *[count];
        for (unsigned i = 0; i < count; i++)
          arr[i] = va_arg(marker, void *);
        va_end( marker );
      };
      ~__NSContainer_literal() {
        delete[] arr;
      }
    };
    extern "C" __declspec(dllimport) void * objc_autoreleasePoolPush(void);
    extern "C" __declspec(dllimport) void objc_autoreleasePoolPop(void *);
    
    struct __AtAutoreleasePool {
      __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
      ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
      void * atautoreleasepoolobj;
    };
    
    #define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)
    
    typedef signed char __int8_t;
    
    
    
    typedef unsigned char __uint8_t;
    typedef short __int16_t;
    typedef unsigned short __uint16_t;
    typedef int __int32_t;
    typedef unsigned int __uint32_t;
    typedef long long __int64_t;
    typedef unsigned long long __uint64_t;
    
    typedef long __darwin_intptr_t;
    typedef unsigned int __darwin_natural_t;
    typedef int __darwin_ct_rune_t;
    
    
    
    
    
    typedef union {
     char __mbstate8[128];
     long long _mbstateL;
    } __mbstate_t;
    
    typedef __mbstate_t __darwin_mbstate_t;
    
    
    typedef long int __darwin_ptrdiff_t;
    
    
    
    
    
    
    
    typedef long unsigned int __darwin_size_t;
    
    
    
    
    
    typedef __builtin_va_list __darwin_va_list;
    
    
    
    
    
    typedef int __darwin_wchar_t;
    
    
    
    
    typedef __darwin_wchar_t __darwin_rune_t;
    
    
    typedef int __darwin_wint_t;
    
    
    
    
    typedef unsigned long __darwin_clock_t;
    typedef __uint32_t __darwin_socklen_t;
    typedef long __darwin_ssize_t;
    typedef long __darwin_time_t;
    typedef __int64_t __darwin_blkcnt_t;
    typedef __int32_t __darwin_blksize_t;
    typedef __int32_t __darwin_dev_t;
    typedef unsigned int __darwin_fsblkcnt_t;
    typedef unsigned int __darwin_fsfilcnt_t;
    typedef __uint32_t __darwin_gid_t;
    typedef __uint32_t __darwin_id_t;
    typedef __uint64_t __darwin_ino64_t;
    
    typedef __darwin_ino64_t __darwin_ino_t;
    
    
    
    typedef __darwin_natural_t __darwin_mach_port_name_t;
    typedef __darwin_mach_port_name_t __darwin_mach_port_t;
    typedef __uint16_t __darwin_mode_t;
    typedef __int64_t __darwin_off_t;
    typedef __int32_t __darwin_pid_t;
    typedef __uint32_t __darwin_sigset_t;
    typedef __int32_t __darwin_suseconds_t;
    typedef __uint32_t __darwin_uid_t;
    typedef __uint32_t __darwin_useconds_t;
    typedef unsigned char __darwin_uuid_t[16];
    typedef char __darwin_uuid_string_t[37];
    
    
    struct __darwin_pthread_handler_rec {
     void (*__routine)(void *);
     void *__arg;
     struct __darwin_pthread_handler_rec *__next;
    };
    
    struct _opaque_pthread_attr_t {
     long __sig;
     char __opaque[56];
    };
    
    struct _opaque_pthread_cond_t {
     long __sig;
     char __opaque[40];
    };
    
    struct _opaque_pthread_condattr_t {
     long __sig;
     char __opaque[8];
    };
    
    struct _opaque_pthread_mutex_t {
     long __sig;
     char __opaque[56];
    };
    
    struct _opaque_pthread_mutexattr_t {
     long __sig;
     char __opaque[8];
    };
    
    struct _opaque_pthread_once_t {
     long __sig;
     char __opaque[8];
    };
    
    struct _opaque_pthread_rwlock_t {
     long __sig;
     char __opaque[192];
    };
    
    struct _opaque_pthread_rwlockattr_t {
     long __sig;
     char __opaque[16];
    };
    
    struct _opaque_pthread_t {
     long __sig;
     struct __darwin_pthread_handler_rec *__cleanup_stack;
     char __opaque[8176];
    };
    
    typedef struct _opaque_pthread_attr_t __darwin_pthread_attr_t;
    typedef struct _opaque_pthread_cond_t __darwin_pthread_cond_t;
    typedef struct _opaque_pthread_condattr_t __darwin_pthread_condattr_t;
    typedef unsigned long __darwin_pthread_key_t;
    typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
    typedef struct _opaque_pthread_mutexattr_t __darwin_pthread_mutexattr_t;
    typedef struct _opaque_pthread_once_t __darwin_pthread_once_t;
    typedef struct _opaque_pthread_rwlock_t __darwin_pthread_rwlock_t;
    typedef struct _opaque_pthread_rwlockattr_t __darwin_pthread_rwlockattr_t;
    typedef struct _opaque_pthread_t *__darwin_pthread_t;
    typedef int __darwin_nl_item;
    typedef int __darwin_wctrans_t;
    
    typedef __uint32_t __darwin_wctype_t;
    
    
    
    typedef __darwin_va_list va_list;
    typedef __darwin_size_t size_t;
    
    extern "C" {
    
    int renameat(int, const char *, int, const char *) __attribute__((availability(macosx,introduced=10.10)));
    
    
    
    
    
    
    int renamex_np(const char *, const char *, unsigned int) __attribute__((availability(macosx,introduced=10.12))) __attribute__((availability(ios,introduced=10.0))) __attribute__((availability(tvos,introduced=10.0))) __attribute__((availability(watchos,introduced=3.0)));
    int renameatx_np(int, const char *, int, const char *, unsigned int) __attribute__((availability(macosx,introduced=10.12))) __attribute__((availability(ios,introduced=10.0))) __attribute__((availability(tvos,introduced=10.0))) __attribute__((availability(watchos,introduced=3.0)));
    
    
    
    }
    
    typedef __darwin_off_t fpos_t;
    struct __sbuf {
     unsigned char *_base;
     int _size;
    };
    
    
    struct __sFILEX;
    typedef struct __sFILE {
     unsigned char *_p;
     int _r;
     int _w;
     short _flags;
     short _file;
     struct __sbuf _bf;
     int _lbfsize;
    
    
     void *_cookie;
     int (* _Nullable _close)(void *);
     int (* _Nullable _read) (void *, char *, int);
     fpos_t (* _Nullable _seek) (void *, fpos_t, int);
     int (* _Nullable _write)(void *, const char *, int);
    
    
     struct __sbuf _ub;
     struct __sFILEX *_extra;
     int _ur;
    
    
     unsigned char _ubuf[3];
     unsigned char _nbuf[1];
    
    
     struct __sbuf _lb;
    
    
     int _blksize;
     fpos_t _offset;
    } FILE;
    
    extern "C" {
    extern FILE *__stdinp;
    extern FILE *__stdoutp;
    extern FILE *__stderrp;
    }
    extern "C" {
    void clearerr(FILE *);
    int fclose(FILE *);
    int feof(FILE *);
    int ferror(FILE *);
    int fflush(FILE *);
    int fgetc(FILE *);
    int fgetpos(FILE * , fpos_t *);
    char *fgets(char * , int, FILE *);
    
    
    
    FILE *fopen(const char * __filename, const char * __mode) __asm("_" "fopen" );
    
    int fprintf(FILE * , const char * , ...) __attribute__((__format__ (__printf__, 2, 3)));
    int fputc(int, FILE *);
    int fputs(const char * , FILE * ) __asm("_" "fputs" );
    size_t fread(void * __ptr, size_t __size, size_t __nitems, FILE * __stream);
    FILE *freopen(const char * , const char * ,
                     FILE * ) __asm("_" "freopen" );
    int fscanf(FILE * , const char * , ...) __attribute__((__format__ (__scanf__, 2, 3)));
    int fseek(FILE *, long, int);
    int fsetpos(FILE *, const fpos_t *);
    long ftell(FILE *);
    size_t fwrite(const void * __ptr, size_t __size, size_t __nitems, FILE * __stream) __asm("_" "fwrite" );
    int getc(FILE *);
    int getchar(void);
    char *gets(char *);
    void perror(const char *);
    int printf(const char * , ...) __attribute__((__format__ (__printf__, 1, 2)));
    int putc(int, FILE *);
    int putchar(int);
    int puts(const char *);
    int remove(const char *);
    int rename (const char *__old, const char *__new);
    void rewind(FILE *);
    int scanf(const char * , ...) __attribute__((__format__ (__scanf__, 1, 2)));
    void setbuf(FILE * , char * );
    int setvbuf(FILE * , char * , int, size_t);
    int sprintf(char * , const char * , ...) __attribute__((__format__ (__printf__, 2, 3))) __attribute__((__availability__(swift, unavailable, message="Use snprintf instead.")));
    int sscanf(const char * , const char * , ...) __attribute__((__format__ (__scanf__, 2, 3)));
    FILE *tmpfile(void);
    
    __attribute__((__availability__(swift, unavailable, message="Use mkstemp(3) instead.")))
    
    __attribute__((deprecated("This function is provided for compatibility reasons only.  Due to security concerns inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead.")))
    
    char *tmpnam(char *);
    int ungetc(int, FILE *);
    int vfprintf(FILE * , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0)));
    int vprintf(const char * , va_list) __attribute__((__format__ (__printf__, 1, 0)));
    int vsprintf(char * , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))) __attribute__((__availability__(swift, unavailable, message="Use vsnprintf instead.")));
    }
    extern "C" {
    
    
    
    char *ctermid(char *);
    
    
    
    
    
    FILE *fdopen(int, const char *) __asm("_" "fdopen" );
    
    int fileno(FILE *);
    }
    extern "C" {
    int pclose(FILE *) __attribute__((__availability__(swift, unavailable, message="Use posix_spawn APIs or NSTask instead.")));
    
    
    
    FILE *popen(const char *, const char *) __asm("_" "popen" ) __attribute__((__availability__(swift, unavailable, message="Use posix_spawn APIs or NSTask instead.")));
    
    }
    extern "C" {
    int __srget(FILE *);
    int __svfscanf(FILE *, const char *, va_list) __attribute__((__format__ (__scanf__, 2, 0)));
    int __swbuf(int, FILE *);
    }
    
    
    
    
    
    
    
    inline __attribute__ ((__always_inline__)) int __sputc(int _c, FILE *_p) {
     if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
      return (*_p->_p++ = _c);
     else
      return (__swbuf(_c, _p));
    }
    extern "C" {
    void flockfile(FILE *);
    int ftrylockfile(FILE *);
    void funlockfile(FILE *);
    int getc_unlocked(FILE *);
    int getchar_unlocked(void);
    int putc_unlocked(int, FILE *);
    int putchar_unlocked(int);
    
    
    
    int getw(FILE *);
    int putw(int, FILE *);
    
    
    __attribute__((__availability__(swift, unavailable, message="Use mkstemp(3) instead.")))
    
    __attribute__((deprecated("This function is provided for compatibility reasons only.  Due to security concerns inherent in the design of tempnam(3), it is highly recommended that you use mkstemp(3) instead.")))
    
    char *tempnam(const char *__dir, const char *__prefix) __asm("_" "tempnam" );
    }
    typedef __darwin_off_t off_t;
    
    extern "C" {
    int fseeko(FILE * __stream, off_t __offset, int __whence);
    off_t ftello(FILE * __stream);
    }
    
    
    
    extern "C" {
    int snprintf(char * __str, size_t __size, const char * __format, ...) __attribute__((__format__ (__printf__, 3, 4)));
    int vfscanf(FILE * __stream, const char * __format, va_list) __attribute__((__format__ (__scanf__, 2, 0)));
    int vscanf(const char * __format, va_list) __attribute__((__format__ (__scanf__, 1, 0)));
    int vsnprintf(char * __str, size_t __size, const char * __format, va_list) __attribute__((__format__ (__printf__, 3, 0)));
    int vsscanf(const char * __str, const char * __format, va_list) __attribute__((__format__ (__scanf__, 2, 0)));
    }
    typedef __darwin_ssize_t ssize_t;
    
    extern "C" {
    int dprintf(int, const char * , ...) __attribute__((__format__ (__printf__, 2, 3))) __attribute__((availability(macosx,introduced=10.7)));
    int vdprintf(int, const char * , va_list) __attribute__((__format__ (__printf__, 2, 0))) __attribute__((availability(macosx,introduced=10.7)));
    ssize_t getdelim(char ** __linep, size_t * __linecapp, int __delimiter, FILE * __stream) __attribute__((availability(macosx,introduced=10.7)));
    ssize_t getline(char ** __linep, size_t * __linecapp, FILE * __stream) __attribute__((availability(macosx,introduced=10.7)));
    }
    
    
    
    
    
    
    
    extern "C" {
    extern const int sys_nerr;
    extern const char *const sys_errlist[];
    
    int asprintf(char ** , const char * , ...) __attribute__((__format__ (__printf__, 2, 3)));
    char *ctermid_r(char *);
    char *fgetln(FILE *, size_t *);
    const char *fmtcheck(const char *, const char *);
    int fpurge(FILE *);
    void setbuffer(FILE *, char *, int);
    int setlinebuf(FILE *);
    int vasprintf(char ** , const char * , va_list) __attribute__((__format__ (__printf__, 2, 0)));
    FILE *zopen(const char *, const char *, int);
    
    
    
    
    
    FILE *funopen(const void *,
                     int (* _Nullable)(void *, char *, int),
                     int (* _Nullable)(void *, const char *, int),
                     fpos_t (* _Nullable)(void *, fpos_t, int),
                     int (* _Nullable)(void *));
    }
    
    
    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 {
      size_t reserved;
      size_t Block_size;
    } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
    int main()
    {
        void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
    
        ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
        return 0;
    };
    static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
    
    

    相关文章

      网友评论

        本文标题:Block学习笔记一之结构探究

        本文链接:https://www.haomeiwen.com/subject/wcixtxtx.html