runtime 소스 코드 해독 - 데이터 구조

2655 단어
아래 의 모든 소스 코드 는 obbc - 2.0 을 기반 으로 합 니 다.
1. 클래스 와 대상
@interface NSObject  {
    Class isa  OBJC_ISA_AVAILABILITY;
}

typedef struct objc_class *Class;
typedef struct objc_object *id;

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    class_rw_t *data() { 
        return bits.data();
    }
    ...
}

struct objc_object {
private:
    isa_t isa;
    ...
};

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
    ...
    };

클래스 대부분의 데 이 터 를 bits. data () 에 저장 하고 classrw_t
struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;
    ...
};

방법 목록, 속성 목록, 프로 토 콜 목록 을 볼 수 있 습 니 다. 하지만 아직 멤버 목록 이 하나 부족 합 니 다. 이것 은 class 에 저 장 됩 니 다.ro_t, 이 포인터 유형 은 상수 로 컴 파일 러 에서 결정 된다 는 것 을 설명 합 니 다.이 구조 에 도 속성, 프로 토 콜, 방법 목록 이 있 는데 위의 것 과 비교 하면 바로 여기 가 컴 파일 러 에서 생 성 된 것 이 고 위의 것 은 실행 할 때 동적 으로 생 성 된 것 이다.
struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};

참조 링크: ObjC 에서 방법의 구 조 를 깊이 분석 합 니 다.
2. method SEL IMP
모든 class 에는 method 목록 이 있 습 니 다. 데이터 구 조 는 다음 과 같 습 니 다.
struct method_t {
    SEL name;
    const char *types;
    IMP imp;
    ...
};

데이터 구조
typedef struct objc_selector *SEL;

하지만 원본 코드 에는 obbc 가 없습니다.selector 의 정 의 는 자 료 를 조회 함으로써 SEL 이 컴 파일 환경 에 따라 정의 가 다 르 기 때문에 GNU 환경 에서 의 정 의 를 찾 을 수 있 습 니 다.
struct objc_selector
{
  void *sel_id;
  const char *sel_types;
};
//include/onx/runtime/[selector.h]

그래서 SEL 은 함수 라벨 만 저장 한 것 같 습 니 다.IMP 의 정 의 를 봅 시다.
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id (*IMP)(id, SEL, ...); 
#endif

IMP 는 함수 포인터 로 진정한 함수 실현 을 가리킨다.

좋은 웹페이지 즐겨찾기