20

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

4

2 回答 2

27

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


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

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

当对块的调用被编译时,编译器会发出一个蹦床来设置堆栈帧,然后跳转到块内的可执行代码。

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

为此,我为每个类的实例设置了唯一的块实例。如果你想要一个通用块在所有实例中起作用,请为SEL每个类构建一个 -> 块的散列。

(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 将上述蹦床填充到任何选择器中(参见method_setImplementation和喜欢)

注意事项:

  • 这是输入到 StackOverflow 中的。真正的代码将相似,但可能略有不同。

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

于 2009-11-29T23:18:02.227 回答
10

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

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

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

于 2010-09-25T16:45:57.390 回答