boost::shared_ptr<ProtocolPluginInstance> ProtocolPlugin::createInstance(int id, const Licq::UserId& ownerId, void (*callback)(const PluginInstance&)) { PluginThread::Ptr thread; if (myMainThread) thread.swap(myMainThread); else thread = boost::make_shared<PluginThread>(); ProtocolPluginInstance::Ptr instance = boost::make_shared<ProtocolPluginInstance>( id, ownerId, boost::dynamic_pointer_cast<ProtocolPlugin>(shared_from_this()), thread); if (instance->create(callback)) registerInstance(instance); else instance.reset(); return instance; }
GeneralPlugin::Ptr PluginManager::loadGeneralPlugin( const std::string& name, int argc, char** argv, bool keep) { PluginThread::Ptr pluginThread; if (myGuiThread && name.find("-gui") != std::string::npos) { gLog.debug("Running %s in GUI thread", name.c_str()); pluginThread.swap(myGuiThread); } else pluginThread.reset(new PluginThread); DynamicLibrary::Ptr lib = loadPlugin(pluginThread, name, "licq"); if (!lib) return GeneralPlugin::Ptr(); try { // Get plugin data from library struct Licq::GeneralPluginData* pluginData; lib->getSymbol("LicqGeneralPluginData", &pluginData); // Verify plugin data if (pluginData == NULL || pluginData->licqMagic[0] != 'L' || pluginData->licqMagic[1] != 'i' || pluginData->licqMagic[2] != 'c' || pluginData->licqMagic[3] != 'q') { gLog.error(tr("Library %s does not contain a Licq plugin"), name.c_str()); return GeneralPlugin::Ptr(); } // Make sure plugin version is supported // We expect plugin API to stay the same between releases of the same major/minor version if (pluginData->licqVersion / 10 != LICQ_VERSION / 10) { gLog.error(tr("Plugin in library %s was built for another Licq version (%i.%i.%i)"), name.c_str(), Licq::extractMajorVersion(pluginData->licqVersion), Licq::extractMinorVersion(pluginData->licqVersion), Licq::extractReleaseVersion(pluginData->licqVersion)); return GeneralPlugin::Ptr(); } // Generate an ID for the plugin int pluginId; { // Lock both plugin mutexes to avoid race for myNextPluginId MutexLocker generalLocker(myGeneralPluginsMutex); MutexLocker protocolLocker(myProtocolPluginsMutex); pluginId = myNextPluginId++; } // Create main plugin object GeneralPlugin::Params pluginParams(pluginId, lib, pluginThread); GeneralPlugin::Ptr plugin(pluginData->pluginFactory(pluginParams), deleteGeneralPlugin); // Let the plugin initialize itself if (!plugin->basePrivate()->callInit(argc, argv, &initPluginCallback)) { gLog.error(tr("Failed to initialize plugin (%s)"), plugin->name().c_str()); throw std::exception(); } if (keep) { MutexLocker generalLocker(myGeneralPluginsMutex); myGeneralPlugins.push_back(plugin); } return plugin; } catch (const DynamicLibrary::Exception& ex) { std::string error = ex.getSystemError(); gLog.error(tr("Failed to load plugin (%s): %s"), name.c_str(), error.c_str()); } catch (const std::exception&) { // Empty } return GeneralPlugin::Ptr(); }