📄 pluginmgr.cxx
字号:
/* * pluginmgr.cxx * * Plugin Manager Class * * Portable Windows Library * * Contributor(s): Snark at GnomeMeeting * * $Log: pluginmgr.cxx,v $ * Revision 1.26 2004/08/16 06:40:59 csoutheren * Added adapters template to make device plugins available via the abstract factory interface * * Revision 1.25 2004/07/12 09:17:21 csoutheren * Fixed warnings and errors under Linux * * Revision 1.24 2004/07/06 10:12:54 csoutheren * Added static integer o factory template to assist in ensuring factories are instantiated * * Revision 1.23 2004/06/30 12:17:06 rjongbloed * Rewrite of plug in system to use single global variable for all factories to avoid all sorts * of issues with startup orders and Windows DLL multiple instances. * * Revision 1.22 2004/06/24 23:10:28 csoutheren * Require plugins to have _pwplugin suffix * * Revision 1.21 2004/06/03 13:30:59 csoutheren * Renamed INSTANTIATE_FACTORY to avoid potential namespace collisions * Added documentaton on new PINSTANTIATE_FACTORY macro * Added generic form of PINSTANTIATE_FACTORY * * Revision 1.20 2004/06/03 12:47:59 csoutheren * Decomposed PFactory declarations to hopefully avoid problems with Windows DLLs * * Revision 1.19 2004/06/01 05:44:57 csoutheren * Added OnShutdown to allow cleanup on exit * * Revision 1.18 2004/05/18 06:01:13 csoutheren * Deferred plugin loading until after main has executed by using abstract factory classes * * Revision 1.17 2004/05/06 11:29:35 rjongbloed * Added "current directory" to default plug in path. * * Revision 1.16 2004/05/02 17:06:42 ykiryanov * Ifdefd inclusion of algorithm for BeOS * * Revision 1.15 2004/05/02 08:37:56 rjongbloed * Fixed loading of plug ins when multiple plug in class sets used. Especially H.323 codecs. * * Revision 1.14 2004/04/22 11:43:48 csoutheren * Factored out functions useful for loading dynamic libraries * * Revision 1.13 2004/04/14 08:12:04 csoutheren * Added support for generic plugin managers * * Revision 1.12 2004/04/09 06:03:47 csoutheren * Cannot do PProcess virtual, so code is now in the plugin manager * * Revision 1.11 2004/04/09 05:54:41 csoutheren * Added ability for application to specify plugin directorories, or to specify directories by environment variable * * Revision 1.10 2004/03/23 04:43:42 csoutheren * Modified plugin manager to allow code modules to be notified when plugins * are loaded or unloaded * * Revision 1.9 2004/02/23 23:56:01 csoutheren * Removed unneeded class * * Revision 1.8 2004/01/18 21:00:15 dsandras * Fixed previous commit thanks to Craig Southeren! * * Revision 1.7 2004/01/17 17:40:57 csoutheren * Changed to only attempt loading of files with the correct library file extension * Changed to handle plugins without a register function * * Revision 1.6 2004/01/17 16:02:59 dereksmithies * make test for plugin names case insensitive. * * Revision 1.5 2003/11/18 10:39:56 csoutheren * Changed PTRACE levels to give better output at trace level 3 * * Revision 1.4 2003/11/12 10:27:11 csoutheren * Changes to allow operation of static plugins under Windows * * Revision 1.3 2003/11/12 06:58:59 csoutheren * Added default plugin directory for Windows * * Revision 1.2 2003/11/12 03:27:25 csoutheren * Initial version of plugin code from Snark of GnomeMeeting with changes * by Craig Southeren of Post Increment * * */#include <ptlib.h>#include <ptlib/pluginmgr.h>#ifndef __BEOS__#include <algorithm>#endif#ifndef P_DEFAULT_PLUGIN_DIR# ifdef _WIN32# define P_DEFAULT_PLUGIN_DIR ".;C:\\PWLIB_PLUGINS"# else# define P_DEFAULT_PLUGIN_DIR ".:/usr/lib/pwlib"# endif#endif#ifdef _WIN32#define DIR_SEP ";"#else#define DIR_SEP ":"#endif#define ENV_PWLIB_PLUGIN_DIR "PWLIBPLUGINDIR"#define PWPLUGIN_SUFFIX "_pwplugin"//////////////////////////////////////////////////////void PPluginManager::LoadPluginDirectory (const PDirectory & dir){ PLoadPluginDirectory<PPluginManager>(*this, dir, PWPLUGIN_SUFFIX); }PStringArray PPluginManager::GetPluginDirs(){ PString env = ::getenv(ENV_PWLIB_PLUGIN_DIR); if (env == NULL) env = P_DEFAULT_PLUGIN_DIR; // split into directories on correct seperator return env.Tokenise(DIR_SEP, TRUE);}PPluginManager & PPluginManager::GetPluginManager(){ static PPluginManager systemPluginMgr; return systemPluginMgr;}BOOL PPluginManager::LoadPlugin(const PString & fileName){ PWaitAndSignal m(pluginListMutex); PDynaLink *dll = new PDynaLink(fileName); if (!dll->IsLoaded()) { PTRACE(4, "Failed to open " << fileName); } else { unsigned (*GetAPIVersion)(); if (!dll->GetFunction("PWLibPlugin_GetAPIVersion", (PDynaLink::Function &)GetAPIVersion)) { PTRACE(3, fileName << " is not a PWLib plugin"); } else { int version = (*GetAPIVersion)(); switch (version) { case 0 : // old-style service plugins, and old-style codec plugins { // declare local pointer to register function void (*triggerRegister)(PPluginManager *); // call the register function (if present) if (dll->GetFunction("PWLibPlugin_TriggerRegister", (PDynaLink::Function &)triggerRegister)) (*triggerRegister)(this); else { PTRACE(3, fileName << " has no registration-trigger function"); } } // fall through to new version case 1 : // factory style plugins // call the notifier CallNotifier(*dll, 0); // add the plugin to the list of plugins pluginList.Append(dll); return TRUE; default: PTRACE(3, fileName << " uses version " << version << " of the PWLIB PLUGIN API, which is not supported"); break; } } } // loading the plugin failed - return error dll->Close(); delete dll; return FALSE;}PStringList PPluginManager::GetPluginTypes() const{ PWaitAndSignal n(serviceListMutex); PStringList result; for (PINDEX i = 0; i < serviceList.GetSize(); i++) { PString serviceType = serviceList[i].serviceType; if (result.GetStringsIndex(serviceType) == P_MAX_INDEX) result.AppendString(serviceList[i].serviceType); } return result;}PStringList PPluginManager::GetPluginsProviding(const PString & serviceType) const{ PWaitAndSignal n(serviceListMutex); PStringList result; for (PINDEX i = 0; i < serviceList.GetSize(); i++) { if (serviceList[i].serviceType *= serviceType) result.AppendString(serviceList[i].serviceName); } return result;}PPluginServiceDescriptor * PPluginManager::GetServiceDescriptor (const PString & serviceName, const PString & serviceType){ PWaitAndSignal n(serviceListMutex); for (PINDEX i = 0; i < serviceList.GetSize(); i++) { if ((serviceList[i].serviceName *= serviceName) && (serviceList[i].serviceType *= serviceType)) return serviceList[i].descriptor; } return NULL;}BOOL PPluginManager::RegisterService(const PString & serviceName, const PString & serviceType, PPluginServiceDescriptor * descriptor){ PWaitAndSignal m(serviceListMutex); // first, check if it something didn't already register that name and type for (PINDEX i = 0; i < serviceList.GetSize(); i++) { if (serviceList[i].serviceName == serviceName && serviceList[i].serviceType == serviceType) return FALSE; } PPluginService * service = new PPluginService(serviceName, serviceType, descriptor); serviceList.Append(service); PDevicePluginAdapterBase * adapter = PFactory<PDevicePluginAdapterBase>::CreateInstance(serviceType); if (adapter != NULL) adapter->CreateFactory(serviceName); return TRUE;}void PPluginManager::AddNotifier(const PNotifier & notifyFunction, BOOL existing){ PWaitAndSignal m(notifierMutex); notifierList.Append(new PNotifier(notifyFunction)); if (existing) for (PINDEX i = 0; i < pluginList.GetSize(); i++) CallNotifier(pluginList[i], 0);}void PPluginManager::RemoveNotifier(const PNotifier & notifyFunction){ PWaitAndSignal m(notifierMutex); for (PINDEX i = 0; i < notifierList.GetSize(); i++) { if (notifierList[i] == notifyFunction) { notifierList.RemoveAt(i); i = 0; continue; } }}void PPluginManager::CallNotifier(PDynaLink & dll, INT code){ PWaitAndSignal m(notifierMutex); for (PINDEX i = 0; i < notifierList.GetSize(); i++) notifierList[i](dll, code);}////////////////////////////////////////////////////////////////////////////////////PPluginModuleManager::PPluginModuleManager(const char * _signatureFunctionName, PPluginManager * _pluginMgr) : signatureFunctionName(_signatureFunctionName){ pluginList.DisallowDeleteObjects(); pluginMgr = _pluginMgr;; if (pluginMgr == NULL) pluginMgr = &PPluginManager::GetPluginManager();}void PPluginModuleManager::OnLoadModule(PDynaLink & dll, INT code){ PDynaLink::Function dummyFunction; if (!dll.GetFunction(signatureFunctionName, dummyFunction)) return; switch (code) { case 0: pluginList.SetAt(dll.GetName(), &dll); break; case 1: { PINDEX idx = pluginList.GetValuesIndex(dll.GetName()); if (idx != P_MAX_INDEX) pluginList.RemoveAt(idx); } break; default: break; } OnLoadPlugin(dll, code);}////////////////////////////////////////////////////////////////////////////////////class PluginLoaderStartup : public PProcessStartup{ PCLASSINFO(PluginLoaderStartup, PProcessStartup); public: void OnStartup() { // load the actual DLLs, which will also load the system plugins PStringArray dirs = PPluginManager::GetPluginDirs(); PPluginManager & mgr = PPluginManager::GetPluginManager(); PINDEX i; for (i = 0; i < dirs.GetSize(); i++) mgr.LoadPluginDirectory(dirs[i]); // now load the plugin module managers PFactory<PPluginModuleManager>::KeyList_T keyList = PFactory<PPluginModuleManager>::GetKeyList(); PFactory<PPluginModuleManager>::KeyList_T::const_iterator r; for (r = keyList.begin(); r != keyList.end(); ++r) { PPluginModuleManager * mgr = PFactory<PPluginModuleManager>::CreateInstance(*r); if (mgr == NULL) { PTRACE(1, "PLUGIN\tCannot create manager for plugins of type " << *r); } else { PTRACE(1, "PLUGIN\tCreated manager for plugins of type " << *r); managers.push_back(mgr); } } } void OnShutdown() { while (managers.begin() != managers.end()) { std::vector<PPluginModuleManager *>::iterator r = managers.begin(); PPluginModuleManager * mgr = *r; managers.erase(r); mgr->OnShutdown(); } } protected: std::vector<PPluginModuleManager *> managers;};PFactory<PProcessStartup>::Worker<PluginLoaderStartup> pluginLoaderStartupFactory("PluginLoader", true);#ifdef _WIN32PINSTANTIATE_FACTORY(PProcessStartup, PString)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -