参考资料:
clang
我们都知道 Objective-C 是 C++ 的超集。Objetive-C 的代码在编译阶段,先会 clang 被编译为 C++ 代码,然后在 Runtime 上运行。
利用 clang 在命令行里编译 Objective-C 的命令:
1
2
3
4
5
  | # ARC
$ clang -fobjc-arc -framework Foundation main.m -o main
# MRC
$ clang -fno-objc-arc -framework Foundation main.m -o main
  | 
我们使用下面的示例程序,来查看 clang 的编译结果:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  | #import <Foundation/Foundation.h>
@interface SheslClass : NSObject {
    NSNumber *sheslVarNumber;
}
@property (nonatomic, copy) NSString *sheslPropertyString;
+ (void)sheslClassMethod;
- (NSNumber *)getSheslVarNumber;
@end
@implementation SheslClass
+ (void)sheslClassMethod { NSLog(@"Hello World"); }
- (NSNumber *)getSheslVarNumber { return sheslVarNumber; }
@end
int main(int argc, char * argv[]) {
    [SheslClass sheslClassMethod];
    SheslClass *sheslClass = [[SheslClass alloc] init];
    return 0;
}
  | 
我们可以手动将 Objetive-C 代码编译为 C++ 代码:
1
  | $ clang -rewrite-objc main.m
  | 
OC 类的实例变量
SheslClass 的实例变量,通过 C++ 实例 _OBJC_$_INSTANCE_VARIABLES_SheslClass 实现,它的定义如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
  | static struct /*_ivar_list_t*/ {
	unsigned int entsize;  // sizeof(struct _prop_t)
	unsigned int count;
	struct _ivar_t ivar_list[2];
} _OBJC_$_INSTANCE_VARIABLES_SheslClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
	sizeof(_ivar_t), 2,
	{
    {
      (unsigned long int *)&OBJC_IVAR_$_SheslClass$sheslVarNumber,
      "sheslVarNumber", "@\"NSNumber\"", 3, 8
    }, {
      (unsigned long int *)&OBJC_IVAR_$_SheslClass$_sheslPropertyString,
      "_sheslPropertyString", "@\"NSString\"", 3, 8
    }
  }
};
  | 
我们分析其中的一个变量 sheslVarNumber:
可见 clang 生成了一个变量 OBJC_IVAR_$_SheslClass$sheslVarNumber 用于存储偏移的地址;
Objetive-C 的变量名和类型在 C++ 中都表现为字符串;
第一个参数存储类型为 unsigned long int * 是地址的强制类型转换,具体的类型由第三个参数确定;
OC 类的实例方法
SheslClass 的实例方法,通过 C++ 实例 _OBJC_$_INSTANCE_METHODS_SheslClass 实现,它的定义如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  | static struct /*_method_list_t*/ {
	unsigned int entsize;  // sizeof(struct _objc_method)
	unsigned int method_count;
	struct _objc_method method_list[3];
} _OBJC_$_INSTANCE_METHODS_SheslClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
	sizeof(_objc_method),
	3,
	{
    {
      (struct objc_selector *)"getSheslVarNumber",
      "@16@0:8",
      (void *)_I_SheslClass_getSheslVarNumber
    }, {
      (struct objc_selector *)"sheslPropertyString",
      "@16@0:8",
      (void *)_I_SheslClass_sheslPropertyString
    }, {
      (struct objc_selector *)"setSheslPropertyString:",
      "v24@0:8@16",
      (void *)_I_SheslClass_setSheslPropertyString_
    }
  }
};
  | 
我们分析其中的第一个变量 getSheslVarNumber:
- 在 Runtime 中,第一个参数类型为 
SEL,它底层是通过 C++ 的 objc_selector 这个结构实现的 - 第二个参数则是方法的类型,字符串的内容看起来是一串神秘的编码,它叫做方法类型编码;这个编码由一个类型与一个字节数构成。比如上面的 
@16@:8:@16 表示这个方法的返回值,是一个 16 个字节的对象;@0 与 :8 是每个选择器都会有的参数,即 id self & SEL op。