iOS-将 .m文件编译成 .cpp文件

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS-将 .m文件编译成 .cpp文件相关的知识,希望对你有一定的参考价值。

我们知道OC开发中,创建的对象文件是xxx.h 和 xxx.m,但是有时候我们也需要将 .m文件转为 C++代码的 .cpp文件,如OC中的Runtime

Runtime 是 OC底层的一套C语言的API(需要import导入 <objc/runtime.h> 或<objc/message.h>)

<objc/runtime.h> //包含对类、成员变量、属性、方法的操作;

<objc/message.h> //包含消息机制

编译器最终都会将OC代码转化为运行时代码,通过终端命令编译 .m 文件:

clang -rewrite-objc xxx.m

可以看到编译后的xxx.cpp(C++文件)
比如我们在ViewController.m中创建了一个对象 [[NSObject alloc]init]

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSObject *objc = [[NSObject alloc]init];
}

然后打开终端Terminal,cd到文件路径,,然后输入命令

clang -rewrite-objc ViewController.m

这时候终端报错了:

In file included from ViewController.m:8:
./ViewController.h:8:9: fatal error: 'UIKit/UIKit.h' file not found
#import <UIKit/UIKit.h>
        ^~~~~~~~~~~~~~~
1 error generated.

找不到 'UIKit/UIKit.h' file文件,因此我们需要执行新的命令

clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk xxx.m

 这时候你会发现相应文件夹下多出了一个ViewController.cpp 文件,如下:
 

我们打开 ViewController.cpp 查看转化后的代码如下:

struct ViewController_IMPL {
	struct UIViewController_IMPL UIViewController_IVARS;
};



/* @end */


// @interface ViewController ()

/* @end */


// @implementation ViewController


static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) {
    ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));

    NSObject *objc = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
}


// @end

我们可以看到调用方法本质就是objc_msgSend发消息[[NSObject alloc]init]语句发了两次消息,第一次发了alloc 消息,第二次发送init 消息。 

我们也可以验证一下

1、调用objc_msgSend,需要导入头文件#import <objc/message.h>

2、TARGET → Build Settings → 搜索 msg → Enable Strict Checking of objc_msgSend CallsYES 改为NO

将严厉的检查机制关掉,如果Enable Strict Checking of objc_msgSend Calls还是YES,则objc_msgSend的参数会报错

Too many arguments to function call, expected 0, have 2

 测试代码:

//obc_msgSend 方法
- (void)testObcMsgSend {
    Person *person = [Person new];
    [person eat];
    
    objc_msgSend(person,sel_registerName("eat"));
}

输出相同; [person eat];等同于objc_msgSend(person,sel_registerName("eat"));

以上是关于iOS-将 .m文件编译成 .cpp文件的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发底层之对象的本质-04

如何将 .cpp 源文件编译成 .dll?

Makefile用于将一些.cpp和.h编译成lib

C++程序编译过程

C++程序编译过程

C++程序编译过程