Objective-C 函数调度冲突;或者说,如何实现“命名空间”?
我有一个适用于 Mac OS X 的应用程序,它支持同时加载的插件。其中一些插件构建在 Cocoa 框架之上,可能会在一个插件中接收更新,但不会在另一个插件中接收更新。鉴于 Objective-C 当前的函数分派方法,从任何插件到给定 Objective-C 例程的任何调用每次都会转到相同的例程。这意味着插件 A 可以通过简单的 Objective-C 调用在插件 B 中找到自己!显然,我们正在寻找的是每个插件与其构建的框架版本进行交互。 我 有 已经 阅读 一些关于 Objective-C 和这种特殊需求的文章,但尚未找到明确的解决方案。
更新:我上面使用的“框架”一词具有误导性:框架是一个静态链接库,内置于需要它的插件中。然而,根据 Objective-C 处理调度的方式,即使这些静态链接的不同代码片段也会在 Objective-C 调度程序中混合在一起,从而导致意想不到的后果。
更新2:我对 此处提供了答案,因为它似乎没有提出解决方案,而是提出了未经证实的假设。
I have an application for Mac OS X that supports plugins that are intended to be loaded at the same time. Some of these plugins are built on top of a Cocoa framework that may receive updates in one plugin but not another. Given Objective-C's current method for function dispatching, any call from any plugin to a given Objective-C routine will go to the same routine every time. That means plugin A can find itself inside plugin B with a trivial Objective-C call! Obviously what we're looking for is for each plugin to interact with its own version of the framework upon which it was built. I have been reading some on Objective-C and this particular need, but haven't found a definitive solution for it yet.
Update: My use of the word "framework" above is misleading: the framework is a statically-linked library, built into the plugin(s) that need it. The way Objective-C handles dispatching, however, even these statically linked pieces of disparate code will co-mingle in the Objective-C dispatcher, leading to unintended consequences.
Update 2: I'm still a bit fuzzy on the answer provided here, as it doesn't seem to propose a solution as much as an unproven hypothesis.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你不能这样做(至少不能这样做),Objective-C 目前没有命名空间的概念,并且运行时仅提供一个(全局)调度表。
请注意,这并不是 Objective-C 所独有的,即使是基于 C 的插件也可以相当简单地相互调用,因为所有内容都在同一地址空间中。诚然,如果您担心意外执行此操作的可能性较小,因为有两级命名空间,但如果某些插件显式尝试输入另一个代码,这些并不能保护您。
如果您确实想要隔离插件,您可以创建单独的帮助程序进程,在其中运行加载插件的代码,并让您的应用程序在其自身和帮助程序应用程序之间执行 RPC。例如,这就是 64 位 Safari 在 Snow Leopard 上所做的事情。这种方法有很多好处,但实施起来相当复杂,并且您必须自己进行大部分操作。
You can't do that (at least not trivially), Objective-C currently has no notion of namespaces, and the runtime only presents a single (global) dispatch table.
Note that this is not unique to Objective-C, even C based plugins can also call between each other fairly trivially, since everything is in the same address space. Admittedly, if you are worried about accidentally doing it is less likely because of two-level namespaces, but those won't protect you if some plugin explicitly tries to enter another code.
If you really want to isolate plugins you can create separate helper processes where you run code that loads the plugin and have your application perform RPCs between itself and the helper apps. This is what Safari does in 64-bit on Snow Leopard, for instance. There are a number of benefits to this approach, but it is fairly complex to implement and you have to roll most of it yourself.
我不认为我理解你关于“插件 A 可以在插件 B 中找到自己”的评论。我猜你的意思是,一旦你加载了一些依赖框架一次,那么每个人都会使用它而不是加载自己的框架,这是正确的。无论您是否有命名空间之类的东西,这都是正确的。
如果一个插件需要一个版本的 OpenSSL,而另一个插件需要另一个版本的 OpenSSL,那么您也会遇到同样的问题。您无法加载两个提供相同符号的库。
我明白问题所在吗?不同的插件需要同一框架的不同的、不兼容的版本?如果可能的话,我的方法是将框架更改为静态库,并将您的插件静态链接到其框架。如果您不在插件之间共享框架,那么框架确实不是您想要的。您只想编译代码(静态链接)。框架的重点是共享。
I don't think I understand you comment about "plugin A can find itself inside plugin B." I'm guessing you mean that once you've loaded some dependent framework once, then everyone will use it rather than loading their own, and that's correct. And that's correct whether you have something like namespaces or not.
This is the same problem you would face if one plugin required one version of OpenSSL, and another plugin required another version of OpenSSL. You can't load two libraries that provide the same symbols.
Do I understand the problem? Various plugins require different, incompatible versions of the same framework? My approach, if possible, would be to change the framework to a static library and statically link your plugins to their framework. If you're not sharing the framework between the plugins, then a framework really isn't what you want. You want to just compile the code (static linking). The whole point of a framework is to share.
迄今为止最好的解决方案是源自 this 中提出的想法问题
The best solution thus far is a derivative from the idea proposed in this question