Re: How to make a plugin?
Re: How to make a plugin?
- Subject: Re: How to make a plugin?
- From: Rainer Brockerhoff <email@hidden>
- Date: Thu, 19 Jul 2001 22:01:57 -0300
Hi folks,
I've got plugins working in my application - thanks, of course, to the collaboration of several of you. Here's what I learned:
First I've defined a formal protocol which must be used by plugins:
@protocol myPluginProtocol
+ (id<myPluginProtocol>) pluginInitialize;
// ... other methods
@end
and I load the plugins as follows (in the app delegate):
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
// iterate over all ".plugin" bundles in the "Plugins" folder
NSEnumerator *enumerator = [[NSBundle pathsForResourcesOfType:@"plugin"
inDirectory:[[NSBundle mainBundle] builtInPlugInsPath]]
objectEnumerator];
// this will contain each plugin's full path
NSString* plg;
while ((plg = [enumerator nextObject])) {
[self activatePlugin:plg];
}
}
// this is a separate method so I can initialize selected plugins separately
-(void)activatePlugin:(NSString*)path {
// this is the plugin's bundle
NSBundle* plugb = [NSBundle bundleWithPath:path];
if (plugb) {
// this will load the bundle and the principal class
Class pclass = [plugb principalClass];
// if the class implements the protocol, instantiate it
if ([pclass conformsToProtocol:@protocol(myPluginProtocol)]) {
id <myPluginProtocol> plugin = [pluginClass pluginInitialize];
// ... store plugin for later use
// ...
}
}
}
and the plugin starts with:
@implementation somePlugin
+ (id<myPluginProtocol>) pluginInitialize {
static id<myPluginProtocol> singleton = nil;
if (!singleton) {
singleton = [[somePlugin alloc] init];
}
return singleton;
}
OK, this all works very well. But there are still some unsolved issues.
1) If I decide not to use a certain plugin anymore, I can deallocate the instantiated object... but I found no way to close the bundle and everything inside it as a whole. (I may even want to erase it entirely.)
Any hints?
2) Should a plugin writer use a class name which has already been used by the application (or by another plugin),
[plugb principalClass]
returns nil. OK, the new plugin won't get installed, but a long and detailed error message is written to the console log, stating that the class already exists.
I found no 100% reliable way of obtaining the bundle's principal class name without calling principalClass and getting the error message. Yes, I could call
[[plugb infoDictionary] objectForKey:@"NSPrincipalClass"]
but if the plugin's author didn't define it for some reason, the first class in the executable is used - and I don't know how to get at that.
3) Even should I find out the principal class' name, how do I call the ObjC runtime to check if this classname is already in use without hitting a runtime error?
Any help will be greatly appreciated. TIA,
--
Rainer Brockerhoff <email@hidden>
Belo Horizonte, Brazil
"In the affairs of others even fools are wise
In their own business even sages err."
http://www.brockerhoff.net/ (updated July 2000)