从 Objective-C 块创建 IMP
据我所知,Objective-C 中的 IMP
类型表示函数指针。有没有办法从块指针创建IMP
?感谢您的想法。
The IMP
type in Objective-C represents a function pointer, as far I as understand. Is there any way to make an IMP
from a block pointer? Thanks for your ideas.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
自本文编写以来,iOS 和 Mac OS X 中现在有 API 允许将块直接转换为 IMP。我写了一个 描述 API (imp_implementationWithBlock()) 的博客文章。
块实际上是一种结构,其中包含一些元数据、对块内包含的代码的引用以及块内捕获的 const 复制数据的副本。
因此,不,没有办法在
IMP
和块引用之间直接映射。当编译对块的调用时,编译器会发出一个蹦床,它设置堆栈帧,然后跳转到块内的可执行代码。
不过,您可以做的是创建一个像蹦床一样运行的 IMP。对于以下内容,您将需要为每组参数和参数设置一个特定的 IMP。返回要调用的类型。如果您需要使其通用,则需要使用汇编。
为此,我为类的每个实例设置唯一的块实例。如果您想要一个跨所有实例起作用的通用块,请构建
SEL
-> 的哈希值。每个班级的块。(1) 使用关联引用机制关联块以充当 IMP。类似于:
(2) 实现一个类似于这样的蹦床 IMP:
(3) 通过 Objective-C 运行时的 API 将上述蹦床填充到任何选择器中(参见
method_setImplementation
等)注意事项:
这被输入到 StackOverflow 中。真实的代码将相似,但可能略有不同。
[实现块复制]至关重要;块在堆栈上开始生命(通常)
Since this was written there is now API in iOS and Mac OS X that allows Blocks to be turned into IMPs directly. I wrote up a weblog post describing the API (imp_implementationWithBlock()).
A block is effectively a structure that contains a bit of metadata, a reference to the code contained within the block and a copy of the const-copied data captured within the block.
Thus, no, there is no way to directly map between an
IMP
and a Block reference.When a call to a block is compiled, the compiler emits a trampoline that sets up the stack frame and then jumps to the executable code within the block.
What you can do, though, is create an IMP that acts like that trampoline. For the following, you will need one specific IMP for each set of arguments & return types to be called. If you need to make this generic, you'll need to use assembly.
For this, I'm setting up unique block instances per instance of the class. If you want to have a generic block that acts across all instances, build a hash of
SEL
-> block per class.(1) Associate blocks to act as IMPs using the associated references mechanism. Something like:
(2) implement a trampoline IMP something like this:
(3) stuff the above trampoline in for any selector via the Objective-C runtime's API (see
method_setImplementation
and like)Caveats:
this was typed into StackOverflow. The real code will be similar, but likely slightly different.
the [implementingBlock copy] is critical; Blocks start life on the stack (usually)
我相信 Mike Ash 在 Landon Fuller 的帮助下,已经解决了一般情况下的这个问题,包括 iOS,这更困难。他在 github 上有一个类,它将把块转换为函数指针。
您可能还想发布公告以及一些有趣的后续内容 -展开关于 cocoa-unbound 的讨论。
更新:现在有上面提到的
imp_implementationWithBlock()
。I believe Mike Ash, with some help from Landon Fuller, has solved this for the general case, including iOS, which is harder. He has a class on github which will turn a block into a function pointer.
You may also want to confer the announcement and some interesting follow-up discussion on cocoa-unbound.
UPDATE: And now there's
imp_implementationWithBlock()
as referred above.