|
From: stephan b. <st...@s1...> - 2004-12-24 19:21:42
|
Yo!
include/pclasses/Plugin/Plugin.h
Deps: Phoenix, Factory, SharedLib, PathFinder, Directory
@Christian: look at the implementation and i think you'll see why i like
PathFinder so much. :)
i changed the Factory interface a bit to make it consistent with the
P1.x plugin interface:
instantiate() ==> create()
isRegistered() ==> provides()
And renamed a couple typedefs (don't remember which ones).
The PluginManager interface is essentially the same as in P1, but it has
been reimplemented from scratch on top of the new Factory. It now has a
searchPath() member, which can be be used to query or modify the
plugins search path. Additionally, clients no longer need to add ".so"
or ".dll" when adding a plugin.
Sample usage:
typedef PluginManager<MyType> PM;
PM & pm = PM::instance();
try {
pm.addPluginDir( ... );
pm.addPluginDir( ... );
//^^^^ "." and PREFIX/{lib,lib/pclasses} are
// already added by default
SharedLib * sh = pm.addPlugin( "psql_mysql" );
// ^^^ might throw SystemError
... do something with sh if you like ...
... sh is owned by pm, not by us ...
if( ! pm.provides( "mysql" ) )
{
// error: i expected mysql to be registered by
// opening psql_mysql.so...
}
} catch( const RuntimeError & re ) {
CERR << re.where() <<"\n\t"<<re.what()<<"\n";
// ^^^^ where() was comitted to CVS earlier today.
}
The returned (SharedLib *) is owned by PM. Clients don't need to watch
this return value - it is mainly for informational purposes, but they
may also hold on to it if they like. Clients may also call sharedLibs()
to get at the list of (SharedLib *) opened by PM. The list is cleaned
up, and each SharedLib deleted, post-main().
Aside from the xxxPlugin() and searchPath() functions, PM is just a
normal Factory subtype.
i'm not 100% sure yet, but i think the idea of the type-specific plugin
manager subclasses is now obsoleted. i believe the following can
replace them:
typedef PluginManager<SQLDriver> SQLDriverPluginFactory;
It may still be useful to subclass them, but at the moment i can't see a
reason to (except one which is too complex to contemplate at the
moment).
An interesting thing about this above typedef is that it uses the same
factory database as:
Factory<SQLDriver,string,P::Sharing::FactoryContext>
which means that the plugin layer can inherently load any types which
have been registered with that base Factory. Conversely, once a
PluginManager loads a DLL containing class registrations, those
factories become available via the base factory, without the base
knowing they come from a DLL.
By changing the 3rd template arg (ContextType) we can narrow or widen
the focus of the factory sharing for a given T. For example, we could
tell 2 Factory<T> types to use different factory databases with:
typedef Factory<T,string,X> F1;
typedef Factory<T,string,Y> F2;
This allows us to install, e.g., 2 different factories for the same T:
F1::instance().registerFactory( "T", func_creating_t );
F2::instance().registerFactory( "T", func_creating_special_t );
The 2 factories may be used for different contexts (as defined by the
ContextType argument).
Anyway... still lots of experimentation to do, but there's the first
try.
One idea i'm playing with, but not sure if it is worth keeping, are
namespace-scope convenience functions:
P::Plugin::addPluginDir<SQLDriver>( "..." );
SharedLib * = P::Plugin::addPlugin<SQLDriver>( "..." );
--
----- st...@s1... http://s11n.net
"...pleasure is a grace and is not obedient to the commands
of the will." -- Alan W. Watts
|