将Xcode中文件转换为C++文件
第一步:打开终端,输入xcodebuild -showsdks 展示sdks,找到最新的模拟器型号:
![](https://img.haomeiwen.com/i2230188/d52b28fd18a8fcd7.png)
第二步:cd到我们需要转换的文件所在的文件夹,注意只是cd到工程是不行的。
比如我们想要转换ViewController.m,必须要cd到这个文件夹才行,不然就提示找不到文件:
![](https://img.haomeiwen.com/i2230188/b2f30e1174ad0eeb.png)
第三步:输入转换的命令即可,注意要把里面模拟器的型号和文件换成你自己的
转换成C++代码命令:xcrun -sdk iphonesimulator12.0 clang -rewrite-objc ViewController.m
包含weak类型数据转换成C++:xcrun -sdk iphonesimulator12.0 clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-12.0 BlockMemoryViewController.m
最后在你的文件夹下面就会多一个cpp文件。大功告成。
将OC中block转为C++代码
在.m文件中写多个不同的block,然后在按照上面的方法,转为C++的代码。.m文件如下:
#import "BlockStructureViewController.h"
typedef void(^eocblock)(void);
@interface BlockStructureViewController () {
UILabel *label;
eocblock instanceBlock;
}
@end
@implementation BlockStructureViewController
/**
1、空的block
2、包含简单类型(如int型)block
3、包含临时的objc对象的block
4、成员变量(objc)
5、包含__block的变量
6、global value
7、全局static value
8、局部static value
*/
//block结构:xcrun -sdk iphonesimulator12.0 clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-12.0 BlockStructureViewController.m
int globalValueOne = 10;
static int staticValue = 5;
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
}
- (void)emptyBlockFunction {
void (^emptyBlock)(void) = ^{
NSLog(@"八点钟学院");
};
emptyBlock();
}
- (void)simpleDataBlockFunction {
int i = 10;
void (^simpleDataBlock)(void) = ^{
NSLog(@"八点钟学院 %d", i);
};
simpleDataBlock();
}
- (void)objcDataBlockFunction {
UILabel *tmpLabel = [[UILabel alloc] init];
void (^objcDataBlock)(void) = ^{
NSLog(@"八点钟学院, %@", tmpLabel);
};
objcDataBlock();
}
- (void)classDataBlockFunction {
void (^classDataBlock)(void) = ^{
NSLog(@"八点钟学院 %@", label);
};
classDataBlock();
}
- (void)blockDataBlockFunction {
__block int a = 100; //a在栈里
void (^blockDataBlock)(void) = ^{
// block会将a存放在堆区(栈区的a指向堆区的a,堆区的a指向自己,所以实际上是同一个a)
a = 1000; //在堆区修改a的值
NSLog(@"八点钟学院, %d", a);
}; //blockDataBlock 在堆区
a = 10; //在栈区修改a的值
blockDataBlock();
NSLog(@"栈区a = %d", a);
}
- (void)globalDataBlockFunction {
void (^globalDataBlock)(void) = ^{
NSLog(@"八点钟学院 %d", globalValueOne);
};
globalDataBlock();
}
- (void)staticDataBlockFunction {
void (^staticDataBlock)(void) = ^{
NSLog(@"八点钟学院 %d", staticValue);
};
staticDataBlock();
}
- (void)tmpStaticDataBlockFunction {
static int b = 11;
instanceBlock = ^{
b = 110;
NSLog(@"八点钟学院 %d", b);
};
b= 100;
instanceBlock();
}
@end
转化为C++代码,对比得到简化后的block的C++代码,如下:
#include "SJBlockCPlus.hpp"
// 全局变量
int thisGlobalValue = 1000;
// 全局静态变量
static int thisStaticValue = 10000;
struct block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct block_desc_0 {
size_t reserved;
size_t Block_size;
} __block_desc_0 = {0, sizeof(struct block_desc_0)};
struct block_impl_0 {
struct block_impl impl;
struct block_desc_0* Desc;
/*这后面跟block的变量参数:
int i; // 普通变量
UILabel *label; // 局部对象
self // 如果是成员变量,需要传self,因为成员变量要通过self进行访问。比如 self->label
*/
int *i; // 这么只能放在结构体block_impl后面,不然会越界,内存顺序中加了一个i,访问不到block_impl
// 构造函数 i(_i) 这是赋值i=_i的意思
block_impl_0(void *fp, struct block_desc_0 *desc, int *_i, int flags=0):i(_i) {
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void block_func_0(struct block_impl_0 *__cself) {
// __cself->i = 100;
// printf("good My Love Ms Zhou == %d \n", __cself->i);
// 传的地址所以修改要加*,打印也要加*转换
*(__cself->i) = 100;
printf("good My Love Ms Zhou == %d \n", *(__cself->i));
// 因为作用域是全局的,所以全局变量和全局静态变量,可以直接访问
// printf("good My Love Ms Zhou == %d \n", thisGlobalValue);
// printf("good My Love Ms Zhou == %d \n", thisStaticValue);
}
void test() {
// 局部静态变量传地址过去(因为地址是存在的,只是作用域和全局变量不一样)
static int tmpStaticValue = 100000;
struct block_impl_0 implTest = block_impl_0((void *)block_func_0, &__block_desc_0, &tmpStaticValue);
// int i = 10;
// struct block_impl_0 implTest = block_impl_0((void *)block_func_0, &__block_desc_0, i);
void (*impTestPointer)() = (void (*)())&implTest;
block_impl *tmpPointer = (block_impl *)impTestPointer;
void (*Func)(block_impl *) = (void (*)(block_impl *))tmpPointer->FuncPtr;
Func(tmpPointer);
// printf("i = %d\n", i);
}
由上可知,block主要是由两个结构体(block_impl和block_impl_0)和一个执行函数(block_func_0)构成。一些需要传的变量加在结构体block_impl_0中。
总的结论:block你可以假想为一个class:变量(外部变量:成员变量,抓取的就是self,非成员变量抓取的就是这个非成员变量)、方法(执行函数)
注意点
修改的时候,要让存在栈区的变量和堆区的变量保持一致,所以在内部传的是地址过去,如下:
- (void)blockDataBlockFunction {
//要让栈区和堆区保持一致,所以修改的时候是传的地址过去,block实现中,实际上是将a转化为了一个结构体
__block int a = 100; //a在栈里
void (^blockDataBlock)(void) = ^{
// block会将a存放在堆区(栈区的a指向堆区的a,堆区的a指向自己,所以实际上是同一个a)
a = 1000; //在堆区修改a的值
NSLog(@"八点钟学院, %d", a);
}; //blockDataBlock 在堆区
a = 10; //在栈区修改a的值
blockDataBlock();
NSLog(@"栈区a = %d", a);
}
![](https://img.haomeiwen.com/i2230188/9ecb48a398b1e806.png)
两个的打印都是1000,栈区的a也因为block中的a(堆区)修改而改变了。
网友评论