Re: How can a plug-in bundle get access to its own resources?
Re: How can a plug-in bundle get access to its own resources?
- Subject: Re: How can a plug-in bundle get access to its own resources?
- From: Steve Christensen <email@hidden>
- Date: Mon, 16 Nov 2009 07:34:31 -0800
I understand your frustration, but as I said, one class instance per
process is a feature of the Objective-C runtime and has been the case
since before there was an OS X. Please understand that having 200 plug-
ins, all using the same class name, is not a typical situation. You
are doing it to simplify your build process, but that's not a good
reason for saying that the runtime behavior needs to change.
It looks like your build process is already modifying a number of
project settings on a per-plugin basis, so adding one more #define
shouldn't break you. Remember that ALL of the classes in your plugins
are visible and loaded in the same way, so if any of the others
besides your plugin's "main" class would have issues being loaded from
a single plugin, then you'll have to make sure their names are unique
as well.
On Nov 15, 2009, at 11:35 PM, Motti Shneor wrote:
Thank you all, and thank you Steve - I think the point is clear now.
However, I'm afraid this limit renders the whole Obj-C interface for
plug-ins impractical for any medium-to-large company with legacy code.
There is nothing more natural than re-implementing an interface
using the same class. Unfortunately, this is also the common
practice in C++, Java and other OO languages. Most applications will
naturally select plugins that fit a specific function by looking for
"those implementing this specific interface" usually ---
implementing the same class! (Yes, I know Java and Obj-C provide
protocols/Interfaces for that).
Our company makes more than 200 professional-class Audio plug-ins,
developed along 14 years or so. They all build from one same code
base, for multi-platform multi-host deployment. It's virtually
impossible to set a separate class name for every exposed class of
every plug-in. Not only this is cumbersome, and hard to interface in
other platforms than Obj-C/Cocoa, it introduces huge pollution to
the "name space" of both our code, and the host-applications code
and other makers plug-ins.
In all other code-deployment mechanisms we encountered (Windows
DLLs. Linux Dynamic libraries. Mac shared-libraries dylibs and even
C/C++ code bundles, there is always a way for a piece of code when
run (usually when initialized) to ask where it comes from (i.e. the
path to the binary file it was loaded from) thus, allowing the code
access its resources.
If Obj-C intentionally lacks name-spaces, then some other
replacement mechanism MUST exist to tell one loaded binary from
another! This,to my opinion directly leads to the Bundle mechanism,
responsible for loading and unloading of the actual code. It is only
very natural to ask that code can access its own resources! what's
simpler than that?
Moreover, Cocoa provides such API (mainBundle) for applications,
which makes perfect sense to everyone. How is it that ONLY
application bundles support this API? After all, every code bundle
is structured the same, and includes resources etc.
I think many plugin code makers, especially those with legacy code,
and cross-platform needs, will have to avoid Obj-C APIs in their
plug-ins. Which is a real pity. The dynamic nature of Obj-C calls
for such API to exist.
Such an obvious deficiency in the Obj-C and Bundle mechanisms can
hardly be tolerated in the long run. The situation is error-prone,
simply because we live in an open-space where other software makers
could easily introduce a class named just like mine, and confuse the
system at runtime. There even isn't an error when two same-namesd
classes are loaded!
The last solution from Steve seems the best way out currently,
although it's a little hard to introduce into our build system. We
currently control the product names and the binaries created using
only the XCode projects facilities --- we use pre-build scripts that
read the "product definition" from an external database, then modify
the Project environment accordingly. The Product name is never hard-
coded, and the high-level interface sources never change to produce
a new product or a variation of it.
Luckily, #define-s can be introduced at the project level. Maybe
we'll just do that, If we can limit the number of exposed classes to
just the plug-in names (over 200 i remind, not including versions
and variations that must live together).
Any Ideas for the Versioning problem? Does anyone have good
experience with the Framework version mechanism?
I saw these
myFramework.framework packages with
myFramework.framework
myFramework.framework/Resources (alias)
myFramework.framework/Versions/
myFramework.framework/Versions/A/
myFramework.framework/Versions/Current (alias)
Structures everywhere --- Do they work right? I mean can a host
application (or host library) load a plug-in by a specific version,
and KNOW FOR SURE that the right library was loaded?
Any references to how-to implement multi-version code bundles?
On 16/11/2009, at 00:51, Steve Christensen wrote:
As has been pointed out several times, it's a really bad idea to have
the same-named class in multiple plugins. The Objective-C runtime
will
load the first class instance it finds (in your case, in the first-
loaded plugin). For all other plugins, when the class is referenced,
that first class instance is used, so calling [NSBundle
bundleForClass:
[self class]] will cause it to return the bundle for that first
plugin, no matter which plugin is asking. This answers your question
about code knowing its containing bundle. You made an assumption
about
where the plug-in's code was loaded that turned out to be incorrect.
If you want to use the same class code for each plug-in, I would
suggest that you use a #define to rename the plug-in class at build
time, and add a per-target definition containing a unique class name.
Then your common class would be renamed automatically for each
target.
If you have to specify the plugin class in, say, your Info.plist, you
could use the same build definition.
@interface PLUGIN_CLASS_NAME
...
@end
@implementation PLUGIN_CLASS_NAME
...
@end
The benefit of going with this model is that you still maintain a
single code base for all of your plugins, even though the class is
renamed on a per-plugin basis; you eliminate the "which plugin am I"
problem you're running into now; and you don't have to worry about
having an older plugin version that happens to load before a newer
version, thus forcing all the newer plug-ins to use the older plug-in
code.
On Nov 15, 2009, at 3:36 AM, Motti Shneor wrote:
Thanks, but the bundleWithIdentifier has its own problems.
1. The identifier is (as far as i know) accessible only from the
bundle itself, which I don't have! I'm circling around here, without
access to my own resources! Must I hard-code the bundle identifier
as a string constant within each of my plug-ins?
2. Even if I DO follow this rule, how can I manage to distinguish
between two bundles that include the same plug-in but from different
versions?
They have the same class, and the same identifier!!!!
Really, Isn't there a way for a library (dll, dylib framework etc)
to know what is its containing bundle?
On 10/11/2009, at 19:42, Douglas Davidson wrote:
On Nov 10, 2009, at 4:59 AM, Motti Shneor wrote:
Thanks guys, but you may have not read all my message ---
The [NSBundle bundleForClass:[self class]];
is unusable for me, because I have many plugins that build from
the
same code, and export the same class (of course --- the same class
name).
Obj-C has no name-spaces, and so, If you load 2 such plugins, and
use the [NSBundle bundleForClass:[self class]] in each of them
independently --- you'll get erroneous answers! both of them will
return the same bundle although they come from different bundles.
This is hardly a system "bug" because there are no namespaces, and
for the same class name there is only one bundle.
As others have said, don't do this. However, to answer your
question,
the other way to locate your bundle is via bundleWithIdentifier:.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden