Re: Plugins (was Re: CoreFoundation question)
Re: Plugins (was Re: CoreFoundation question)
- Subject: Re: Plugins (was Re: CoreFoundation question)
- From: marquis logan <email@hidden>
- Date: Wed, 29 Aug 2001 00:26:13 -0400
something i'm trying, which appears to be working cleanly is just
dumping all the plug-ins in a known location.
/some/where/myplugins
here's a snip:
CFArrayRef bundleArray;
CFURLRef myPluginDir;
CFPlugInRef plugin;
CFIndex i, count;
myPluginDir = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR("/some/where/my/plugins"),
kCFURLPOSIXPathStyle, TRUE);
bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
myPluginDir, NULL);
count = CFArrayGetCount(bundleArray);
for(i = 0; i < count; i++)
{
plugin =
CFBundleGetPlugIn((CFBundleRef)CFArrayGetValueAtIndex(bundleArray, i));
if(!plugin)
continue;
// See if this plug-in implements the Test type.
factories =
CFPlugInFindFactoriesForPlugInTypeInPlugIn(kMyTypeID, plugin);
<snip>
}
from there you can pretty much follow the example code apple has, which
is mostly correct with a few typos.
i just made the _assumption_ that cf would return NULL if a bundle was
not a plug-in (and not abort), the documentation doesn't specify (there
is no documentation), and for now things work.
nibs
On Tuesday, August 28, 2001, at 04:57 PM, Greg Titus wrote:
On Tuesday, August 28, 2001, at 11:01 AM, email@hidden wrote:
I know it's OT, but I wonder if anyone here can help...
[...]
I think that most folks who use a plug-in architecture (well, me,
anyway) want to define one or more types, then be able to dynamically
figure out what plugins provide factories for the type(s), without
having to have prior knowledge of how the plugins will be named. Am I
smoking crack here? So, does anyone know of a way to have the plugin
host dynamically locate candidate plugins?
An approach comes to my mind, but before I go down that path, has
anyone got some good suggestions?
The app could define a location (or some locations), say,
/Library/PlugIns and ~/Library/PlugIns, and enumerate all .plugin
packages found in those locations, instantiate the plugins, and then
look for factories for the types.
My conceptual problem with the approach is that every plugin-host app
must either provide its own subfolder in .../PlugIns (or somewhere
else), or else it will be instantiating CFPlugIns for plugins that
belong to unrelated apps, and no limiting (until memory is exhausted)
how many that might be.
I could find no information from Apple how they recommend partitioning
the plugin store.
The other concern that comes to my mind is that it seems not unlikely
that tools like web browsers and media players might share some plugin
types... so that it becomes preferable in that case to have all
plugins centrally located again, without special subdirectories for
each one.
Has someone got a pointer to better Apple documentation? I've studied
http://developer.apple.com/techpubs/macosx/CoreFoundation/PluginServices/
* pretty thoroughly.
I don't think Apple has anything more specific on this topic. I can
tell you what the structure we use looks like, and that may give you
some ideas...
As you describe above, OmniWeb looks in /Library/PlugIns,
~/Library/PlugIns, and /Network/Library/PlugIns for .plugin packages.
But instead of instantiating all of them, we load the Info.plist inside
as a dictionary and look for a couple custom keys.
The first is "OFRequiredSoftwareVersions" which is a dictionary of keys
(framework or application names) with the value being a version string.
If the .plugin is missing the "OFRequiredSoftwareVersions" key it
obviously isn't meant for us, so we discard it and never attempt to
load it. Otherwise we match each element in the dictionary with our app
name or the names of frameworks which the app loads. If the plugin is
meant for a different application, it will contain a key that doesn't
match our app or framework list and again, it is discarded and never
loaded. Similarly, if the version string doesn't match, the plugin is
out of date and discarded.
Notice that we check not only against the app name but against the
loaded frameworks. Most of our plugins specify only framework names in
the OFRequiredSoftwareVersions section, which means they can be loaded
by more than one application as long as each one uses the required
framework(s). For instance, our imaging framework has a plugin
architecture for parsing and displaying images in different formats (we
can't just use the AppKit directly because we want incremental display
and animations). The gif.plugin, jpeg.plugin, png.plugin, et cetera can
not only be loaded into OmniWeb, but also any other app (say a simple
image viewer) that included the framework with the architecture that
the plugins are based on.
The second key is "OFRegistrations" which is a series of dictionaries
describing what the plugin is actually for. The plugin examination code
basically forwards appropriate chunks of the registration dictionary to
the classes that might load plugins and they can either decide to load
that particular plugin immediately, or store the registration
dictionary and plugin location for later. To use the image plugins as
an example again, their registration dictionaries specify that they can
transform MIME types like "image/gif" or "image/jpeg" or whatever into
an image object. This registration information is stored and the plugin
isn't actually loaded until the first time the application comes upon
some "image/gif" content that needs to be dealt with. It's only at that
point that the plugin is loaded and instantiated.
This is all public code, though like all our other code, not well
documented. OFBundleRegistry and OFBundledClass in the OmniFoundation
framework. It's completely generic and should be useful for any kind of
plugin-based Cocoa application.
Also, as another place to look, you may want to check out Apple's
documentation on IOKit. It has a somewhat similar approach to
describing dependencies and connections in an info dictionary and only
loading driver bundles as needed. It's a little more complex because it
handles full dependency graphs instead of the simpler two level
dependencies (plugin on framework or app) that we manage.
Hope this helps,
--Greg
_______________________________________________
cocoa-dev mailing list
email@hidden
http://www.lists.apple.com/mailman/listinfo/cocoa-dev