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:39:18 -0400
i just remembered core foundation was open source:
CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) {
if (bundle->_plugInData._isPlugIn) {
return (CFPlugInRef)bundle;
} else {
return NULL;
}
}
so the code has a good reason to work.
nibs
On Wednesday, August 29, 2001, at 12:26 AM, marquis logan wrote:
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
_______________________________________________
cocoa-dev mailing list
email@hidden
http://www.lists.apple.com/mailman/listinfo/cocoa-dev