资讯专栏INFORMATION COLUMN

Clang -rewrite-objc

cloud / 3166人阅读

摘要:结论是对的,但要读中间码,不免令人头大。一个简单的办法是用将代码转换成代码,然后分析代码即可。以模板为例,比如在中,有执行打开生成的,可以看到展开后的一大堆定义其中就是存储的成员变量偏移值的全局变量。

在Objective-C类成员变量深度剖析一文中,作者通过分析Clang生成的LLVM中间码得出了如下结论:

LLVM为每个类的每个成员变量都分配了一个全局变量,用于存储该成员变量的偏移值。

结论是对的,但要读LLVM中间码,不免令人头大。一个简单的办法是用

Clang -rewrite-objc *.m

将OC代码转换成C++代码,然后分析C++代码即可。

Let"s do it

以Command Line Tool模板为例,比如

//Dummy.h
@interface Dummy : NSObject {
@public
    int myInt;
}

@end

//Dummy.m
@implementation Dummy
@end

在main.m中,有

#import 
#import "Dummy.h"

int main(int argc, const char * argv[]) {  
    Dummy *dummy = [Dummy new];
    dummy->myInt;
      
    return 0;
}

执行

Clang -rewrite-objc main.m

打开生成的main.cpp,可以看到

//Foundation.h展开后的一大堆C++定义
//...

/* @end */

#ifndef _REWRITER_typedef_Dummy
#define _REWRITER_typedef_Dummy
typedef struct objc_object Dummy;
typedef struct {} _objc_exc_Dummy;
#endif

extern "C" unsigned long OBJC_IVAR_$_Dummy$myInt;
struct Dummy_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int myInt;
};

/* @end */
int main(int argc, const char * argv[]) {
    Dummy *dummy = ((Dummy *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Dummy"), sel_registerName("new"));
    (*(int *)((char *)dummy + OBJC_IVAR_$_Dummy$myInt));

    return 0;
}

其中OBJC_IVAR_$_Dummy$myInt就是存储Dummy的myInt成员变量偏移值的全局变量。

如果用@property,会稍微复杂一些,比如

//Dummy.h
@interface Dummy : NSObject
@property (nonatomic, assign) int myInt;

@end

//Dummy.m
@implementation Dummy
@end

执行

Clang -rewrite-objc Dummy.m

打开生成的Dummy.cpp,可以看到

extern "C" unsigned long OBJC_IVAR_$_Dummy$_myInt;
struct Dummy_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _myInt;
};

// @property (nonatomic, assign) int myInt;

/* @end */


// @implementation Dummy



static int _I_Dummy_myInt(Dummy * self, SEL _cmd) { return (*(int *)((char *)self + OBJC_IVAR_$_Dummy$_myInt)); }
static void _I_Dummy_setMyInt_(Dummy * self, SEL _cmd, int myInt) { (*(int *)((char *)self + OBJC_IVAR_$_Dummy$_myInt)) = myInt; }
// @end

对应property的setter和getter,Clang相应地生成了两个static function,两者都通过OBJC_IVAR_$_Dummy$myInt来访问myInt。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/16992.html

相关文章

  • [转]:如何快速构建一个简单的程序

    摘要:例如顺便说一下,在下编译,是完全支持多任务的哦,默认就是自动多任务构建的,比起以前在里面用来编译快多了,因为下的就算你启用了也没啥效果,非常非常得慢。。。 首先我们通过内置的工程模板创建一个空工程: $ xmake create -P ./hello create hello ... create ok!? 这个时候xmake将会产生一些工程文件,如下: $ cd ./hello $...

    willin 评论0 收藏0
  • 安装完Linux后相关配置

    摘要:设置的密码修改更新源源安装语言包修改系统时间拼音五笔谷歌拼音输入法拼音输入法中文乱码升级系统组件安装安装新立得先卸载系统自带的输入法 1.sudo apt-get update && sudo apt-get upgrade 2.设置root的密码 sudo passwd root 3.修改更新源 sudo cp /etc/apt/sources.list /etc/apt...

    levius 评论0 收藏0
  • 基于LLVM开发Clang插件进行代码风格检查

    摘要:其实和我还没有好好研究过,之前大部分都是用开发,代码风格检查都是用的,所以这次选择的代码检查作为开始,通过实践找找感觉和兴趣,之后再一点一点精进。这个很多人都做过,文章也挺多的,我也是参考别人文章的,不过直到真正实现还是踩了许多坑,所以记录下来,或许对其他人有帮助。其实LLVM和Clang我还没有好好研究过,之前大部分都是用Swift开发,代码风格检查都是用的Swiftlint,所以这次选择...

    Raaabbit 评论0 收藏0
  • 征服恐惧!用 Vim 写 iOS App

    摘要:我们都知道和都是文本编辑器中的上古神器,你也许用,配合完成过大型或者的开发,你也许配合过其他插件,完成过,代码的开发,但是很少有人试过的开发吧,毕竟的框架包含了很多东西,以及天生很长的名字,让我们没办法把此神器用起来,今天我就来给大家讲下 我们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的...

    endless_road 评论0 收藏0
  • 征服恐惧!用 Vim 写 iOS App

    摘要:我们都知道和都是文本编辑器中的上古神器,你也许用,配合完成过大型或者的开发,你也许配合过其他插件,完成过,代码的开发,但是很少有人试过的开发吧,毕竟的框架包含了很多东西,以及天生很长的名字,让我们没办法把此神器用起来,今天我就来给大家讲下 我们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的...

    lmxdawn 评论0 收藏0
  • iOS实现依赖注入

    摘要:依赖注入这个词,源于,但在框架中也是十分常见的。举例来说的初始化方法这里的传入值,就是所谓的依赖,这个实例化是根据注入实现的。 依赖注入(Dependency Injection)这个词,源于java,但在Cocoa框架中也是十分常见的。举例来说:UIView的初始化方法initWithFrame - (id)initWithFrame:(CGRect)frame NS_DESIGNA...

    Taste 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<