#include "tpluginmanager.h" #include "tsystem.h" #include "tconvert.h" #include "tlogger.h" #ifdef WIN32 #include #else // QUALE DI QUESTI SERVE VERAMENTE?? #include #include #include #include #include #include // for ftime #include #include #include #include #include // for getfsstat #ifdef MACOSX #include #endif #include #include #include #endif //----------------------------------------------------------------------------- class TPluginManager::Plugin { public: #ifdef WIN32 typedef HINSTANCE Handle; #else typedef void *Handle; #endif private: Handle m_handle; TPluginInfo m_info; public: Plugin(Handle handle) : m_handle(handle) { } Handle getHandle() const { return m_handle; } const TPluginInfo &getInfo() const { return m_info; } void setInfo(const TPluginInfo &info) { m_info = info; } string getName() const { return m_info.getName(); } }; //----------------------------------------------------------------------------- typedef const TPluginInfo *TnzLibMainProcType(); //-------------------------------------------------------------- namespace { const char *TnzLibMainProcName = "TLibMain"; #if !defined(WIN32) const char *TnzLibMainProcName2 = "_TLibMain"; #endif } //============================================================================= TPluginManager::TPluginManager() { m_ignoreList.insert("tnzimagevector"); } //----------------------------------------------------------------------------- TPluginManager::~TPluginManager() { // try { unloadPlugins(); } catch(...) {} } //----------------------------------------------------------------------------- TPluginManager *TPluginManager::instance() { static TPluginManager _instance; return &_instance; } //----------------------------------------------------------------------------- bool TPluginManager::isIgnored(string name) const { return m_ignoreList.count(toLower(name)) > 0; } //----------------------------------------------------------------------------- void TPluginManager::unloadPlugins() { for (PluginTable::iterator it = m_pluginTable.begin(); it != m_pluginTable.end(); ++it) { Plugin::Handle handle = (*it)->getHandle(); #ifndef LINUX #ifdef WIN32 FreeLibrary(handle); #else dlclose(handle); #endif #endif delete (*it); } m_pluginTable.clear(); } //-------------------------------------------------------------- void TPluginManager::loadPlugin(const TFilePath &fp) { if ((int)m_loadedPlugins.count(fp) > 0) { TLogger::debug() << "Already loaded " << fp; return; } string name = fp.getName(); if (isIgnored(name)) { TLogger::debug() << "Ignored " << fp; return; } TLogger::debug() << "Loading " << fp; #ifdef WIN32 Plugin::Handle handle = LoadLibraryW(fp.getWideString().c_str()); #else wstring str_fp = fp.getWideString(); Plugin::Handle handle = dlopen(toString(str_fp).c_str(), RTLD_NOW); // RTLD_LAZY #endif if (!handle) { // non riesce a caricare la libreria; TLogger::warning() << "Unable to load " << fp; #ifdef WIN32 wstring getFormattedMessage(DWORD lastError); TLogger::warning() << toString(getFormattedMessage(GetLastError())); #else TLogger::warning() << dlerror(); #endif } else { m_loadedPlugins.insert(fp); Plugin *plugin = new Plugin(handle); m_pluginTable.push_back(plugin); //cout << "loaded" << endl; TnzLibMainProcType *tnzLibMain = 0; #ifdef WIN32 tnzLibMain = (TnzLibMainProcType *) GetProcAddress(handle, TnzLibMainProcName); #else tnzLibMain = (TnzLibMainProcType *) dlsym(handle, TnzLibMainProcName); if (!tnzLibMain) //provo _ come prefisso tnzLibMain = (TnzLibMainProcType *)dlsym(handle, TnzLibMainProcName2); #endif if (!tnzLibMain) { // La libreria non esporta TLibMain; TLogger::warning() << "Corrupted " << fp; #ifdef WIN32 FreeLibrary(handle); #else dlclose(handle); #endif } else { const TPluginInfo *info = tnzLibMain(); if (info) plugin->setInfo(*info); } } } //-------------------------------------------------------------- void TPluginManager::loadPlugins(const TFilePath &dir) { #if defined(WIN32) const string extension = "dll"; #elif defined(LINUX) || defined(__sgi) const string extension = "so"; #elif defined(MACOSX) const string extension = "dylib"; #endif TFilePathSet dirContent = TSystem::readDirectory(dir, false); if (dirContent.empty()) return; for (TFilePathSet::iterator it = dirContent.begin(); it != dirContent.end(); it++) { TFilePath fp = *it; if (fp.getType() != extension) continue; wstring fullpath = fp.getWideString(); #ifdef WIN32 bool isDebugLibrary = (fullpath.find(L".d.") == fullpath.size() - (extension.size() + 3)); #ifdef _DEBUG if (!isDebugLibrary) #else if (isDebugLibrary) #endif continue; #endif try { loadPlugin(fp); } catch (...) { TLogger::warning() << "unexpected error loading " << fp; } } } //-------------------------------------------------------------- void TPluginManager::loadStandardPlugins() { TFilePath pluginsDir = TSystem::getDllDir() + "plugins"; //loadPlugins(pluginsDir + "io"); loadPlugins(pluginsDir + "fx"); } //-------------------------------------------------------------- void TPluginManager::setIgnoredList(const std::set &names) { m_ignoreList.clear(); for (std::set::const_iterator it = names.begin(); it != names.end(); ++it) m_ignoreList.insert(toLower(*it)); }