美文网首页
iOS 1.NSObject--- clang编译OC成C+

iOS 1.NSObject--- clang编译OC成C+

作者: 龙之天下 | 来源:发表于2019-10-27 17:28 被阅读0次

    1.声明一个类:BaseObj

    BaseObj.h
    @interface BaseObj : NSObject
    @end
    
    BaseObj.m
    NS_ASSUME_NONNULL_END
    @implementation BaseObj
    @end
    

    2.clang编译OC成C++或者C文件

        $:cd --BaseObj的文件路径
        $: clang -rewrite-objc BaseObj.m
    

    3.OC--->C++或者C的源码

     #pragma clang assume_nonnull begin
     #ifndef _REWRITER_typedef_BaseObj
     #define _REWRITER_typedef_BaseObj
     typedef struct objc_object BaseObj;
     typedef struct {} _objc_exc_BaseObj;
    #endif
    
    struct BaseObj_IMPL {
      struct NSObject_IMPL NSObject_IVARS;
      // 如果有属性 : 1.编译期间生成成员变量
      // NSString * _Nonnull _name;
    };
    /* @end */
    #pragma clang assume_nonnull end
    // @implementation BaseObj
    // @end
    

    /*
      * 存放property的结构体
     * 具体存储的数据为_prop_list_t
           原型:@property (copy,nonatomic)NSString *name;
          实际内容:{{"name","T@\"NSString\",C,N,V_name"}}
    
    **/
    struct _prop_t {
      const char *name;
      const char *attributes;
    };
    

    struct _protocol_t;
    

    /*
     *类中方法的结构体,cmd和imp的关系是一一对应的关系
     *创建对象生成isa指针,指向这个对象的结构体时
     *同时生成了一个表"Dispatch table"通过这个  _cmd的编号找到对应方法
    *使用场景:
    *例如方法交换,方法判断。。。
    **/
    struct _objc_method {
    struct objc_selector * _cmd;  //SEL 对应着OC中的@selector()
        const char *method_type;   //方法的类型
        void  *_imp;              //方法的地址
    };
    

    /*
      * 表示这个类中所遵守的协议对象
      * 使用场景:
      * 判断类是否遵守这个协议,从而动态添加、重写、交换某些方法,来达到某些目的
      *
      **/
      struct _protocol_t {
         void * isa;  // NULL
         const char *protocol_name;
         const struct _protocol_list_t * protocol_list; // super protocols
         const struct method_list_t *instance_methods;// 实例方法
         const struct method_list_t *class_methods;//类方法
         const struct method_list_t *optionalInstanceMethods;//可选的实例方法
         const struct method_list_t *optionalClassMethods;//可选的类方法
         const struct _prop_list_t * properties;  //属性列表
         const unsigned int size;  // sizeof(struct _protocol_t)
         const unsigned int flags;  // = 0
         const char ** extendedMethodTypes;//扩展的方法类型
      };
    

      /*
     * 类的成员变量的结构体
     * 原型: NSString *name;
     * 存储内容:
     *{(unsigned long int *)&OBJC_IVAR_$_SLObject_var$_name, "_name", "@\"NSString\"", 3, 8}
    **/
    
    struct _ivar_t {
      unsigned long int *offset;  // pointer to ivar offset location
      const char *name;  //名字
      const char *type;
      unsigned int alignment;
      unsigned int  size;   //大小
    };
    

      /*
       *  这个就是类中的各种方法、属性、等等信息
       *  底层也是一个结构体
       *  名称、方法列表、协议列表、变量列表、layout、properties。。
       **/
     struct _class_ro_t {
      unsigned int flags;        //1
      unsigned int instanceStart;  //sizeof(struct _class_t), sizeof(struct _class_t)
      unsigned int instanceSize;    //
      unsigned int reserved;         //
      const unsigned char *ivarLayout; //
      const char *name;                  //"SLGame"
      const struct _method_list_t *baseMethods;//方法列表
      const struct _objc_protocol_list *baseProtocols;//协议列表
      const struct _ivar_list_t *ivars;//成员变量列表
      const unsigned char *weakIvarLayout;//弱引用布局。
      const struct _prop_list_t *properties;//属性列表。
    };
    

    /*
     * 类本身
     * oc在创建类的时候都会创建一个 _class_t的结构体
     * 我的理解是在runtime中的object-class结构体在底层就会变成_class_t结构体
     */
    
    struct _class_t {
      struct _class_t *isa;  //元类的指针
      struct _class_t *superclass;//父类的指针
      void *cache;  //缓存
      void *vtable;
      struct _class_ro_t *ro;  //这个就是类中的各种方法、属性、等等信息
    };
    

    /*
     * 类扩展的结构体
     * 在OC中写的分类
     **/
    struct _category_t {
      const char *name;  //名称
      struct _class_t *cls;  //这个是哪个类的扩展
      const struct _method_list_t *instance_methods;//实例方法列表
      const struct _method_list_t *class_methods;//类方法列表
      const struct _protocol_list_t *protocols;//协议列表
      const struct _prop_list_t *properties;//属性列表
    };
    

    extern "C" __declspec(dllimport) struct objc_cache _objc_empty_cache;
    #pragma warning(disable:4273)
    

    2.实例

    static struct _class_ro_t _OBJC_METACLASS_RO_$_BaseObj __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    1, sizeof(struct _class_t), sizeof(struct _class_t),
    (unsigned int)0,
    0,
    "BaseObj",
    0,
    0,
    0,
    0,
    0,
    };
    
    static struct _class_ro_t _OBJC_CLASS_RO_$_BaseObj __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    0, sizeof(struct BaseObj_IMPL), sizeof(struct BaseObj_IMPL),
    (unsigned int)0,
    0,
    "BaseObj",
    0,
    0,
    0,
    0,
    0,
    };
    

    extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;
    
    extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_BaseObj __attribute__ ((used, section ("__DATA,__objc_data"))) = {
    0, // &OBJC_METACLASS_$_NSObject,
    0, // &OBJC_METACLASS_$_NSObject,
    0, // (void *)&_objc_empty_cache,
    0, // unused, was (void *)&_objc_empty_vtable,
    &_OBJC_METACLASS_RO_$_BaseObj,
    };
    
    extern "C" __declspec(dllimport) struct _class_t OBJC_CLASS_$_NSObject;
    
    extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_BaseObj __attribute__ ((used, section ("__DATA,__objc_data"))) = {
    0, // &OBJC_METACLASS_$_BaseObj,
    0, // &OBJC_CLASS_$_NSObject,
    0, // (void *)&_objc_empty_cache,
    0, // unused, was (void *)&_objc_empty_vtable,
    &_OBJC_CLASS_RO_$_BaseObj,
    };
    

    static void OBJC_CLASS_SETUP_$_BaseObj(void ) {
      OBJC_METACLASS_$_BaseObj.isa = &OBJC_METACLASS_$_NSObject;
      OBJC_METACLASS_$_BaseObj.superclass = &OBJC_METACLASS_$_NSObject;
      OBJC_METACLASS_$_BaseObj.cache = &_objc_empty_cache;
      OBJC_CLASS_$_BaseObj.isa = &OBJC_METACLASS_$_BaseObj;
      OBJC_CLASS_$_BaseObj.superclass = &OBJC_CLASS_$_NSObject;
      OBJC_CLASS_$_BaseObj.cache = &_objc_empty_cache;
    }
    

    #pragma section(".objc_inithooks$B", long, read, write)
    __declspec(allocate(".objc_inithooks$B")) static void *OBJC_CLASS_SETUP[] = {
         (void *)&OBJC_CLASS_SETUP_$_BaseObj,
    };
    static struct _class_t *L_OBJC_LABEL_CLASS_$ [1] __attribute__((used, section ("__DATA, __objc_classlist,regular,no_dead_strip")))= {
    &OBJC_CLASS_$_BaseObj,
    };
    static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
    

    简单总结:编译--->运行时

     .h文件
     1.编译期间生成成员变量比如:_name(@property (nonatomic,copy) NSString *name;)
    
     .m
      1)、自动生成成员变量 2)、setter  3)、get
    
    2.自动生成property的结构体(name名字 attributes)
    3._objc_method 类对象的(SEL 对应着OC中的@selector(),类型和地址)方法的结构体
    4._protocol_t的结构体(isa,protocol_name,super protocols,instance_methods,class_methods,optionalInstanceMethods,optionalClassMethods,properties,size,flags,extendedMethodTypes)
    5._ivar_t 成员变量结构体(offset,name,type,size)
    6.类的实例结构体(class_ro_t 存储的大多是类在编译时就已经确定的信息。(区别于class_rw_t, 提供了运行时对类拓展的能力)。)
    7.类本身的结构体(isa;  //元类的指针  superclass;//父类的指针 cache //缓存  vtable
     ro:指向常量的指针,其中存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。   )
    
    8.类扩展的结构体
    ( name;  //名称
       cls;  //哪个类的扩展
       instance_methods;//实例方法列表
       class_methods;//类方法列表
       protocols;//协议列表
       properties;//属性列表)
    

    相关文章

      网友评论

          本文标题:iOS 1.NSObject--- clang编译OC成C+

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