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 |