繁体   English   中英

从Objective-C块创建IMP

[英]Creating an IMP from an Objective-C block

Objective-C中的IMP类型表示函数指针,据我所知。 有没有办法从块指针创建IMP 谢谢你的想法。

由于这是编写的,现在iOS和Mac OS X中的API允许块直接转换为IMP。 我写了一篇描述API的博客帖子 (imp_implementationWithBlock())。


块实际上是包含一些元数据的结构,对块中包含的代码的引用以及块内捕获的const复制数据的副本。

因此,不,没有办法在IMP和Block引用之间直接映射。

编译块调用时,编译器会发出一个设置堆栈帧的trampoline,然后跳转到块中的可执行代码。

但是,你可以做的是创建一个像蹦床一样的IMP。 对于以下内容,您将需要为每组参数和返回类型调用一个特定的IMP。 如果您需要使这个通用,您将需要使用程序集。

为此,我在每个类的实例中设置唯一的块实例。 如果您想拥有一个跨所有实例的通用块,请为每个类构建一个SEL - > block的哈希。

(1)使用关联的引用机制关联块以充当IMP。 就像是:

void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
     // do something here
}

objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));

(2)实现这样的蹦床IMP:

void void_id_sel_intTramp(id self, SEL _cmd, int value) {
    int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
    block(self, _cmd, value);
}

(3)通过Objective-C运行时的API将上面的trampoline method_setImplementation任何选择器(参见method_setImplementation等)

注意事项:

  • 这被输入StackOverflow。 真正的代码将类似,但可能略有不同。

  • [implementationBlock copy]很关键; 块开始在堆栈上生活(通常)

我相信Mike Ash在Landon Fuller的帮助下已经解决了一般情况,包括iOS,这更难。 他在github上有一个类,它将块转换为函数指针。

您可能还想要发布关于cocoa-unbound的公告和一些有趣的后续讨论。

更新:现在有上面提到的imp_implementationWithBlock()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM