Delta3d插件机制

Delta3d插件机制主要通过以下两个类实现:

class MainWindow;/**Abstract interface class for STAGE plugins*/class Plugin{public:virtual ~Plugin() {}   /** Is called after instantiation */virtual void Create() {}/** Is called before destruction */virtual void Destroy() {}};/** A plugin factory is used by the plugin manager to identify availableplugins and instantiate them.*/class PluginFactory{public:PluginFactory(): mIsSystemPlugin(false){}virtual ~PluginFactory() {}/** construct the plugin and return a pointer to it */virtual Plugin* Create(MainWindow* mw) = 0;/** delete the plugin */virtual void Destroy() = 0;/** get the name of the plugin */virtual std::string GetName() = 0;/** get a description of the plugin */virtual std::string GetDescription() = 0;/** fill list with names of all plugins this plugin depends on.WARNING: circular dependencies are not handled andwill cause a crash!*/virtual void GetDependencies(std::list<std::string>&) {};/** get the version of STAGE that the plugin is compiled against Only plugins compiled against the current version of STAGE are started*/virtual std::string GetExpectedSTAGEVersion() { // should be replaced by SVN to give version numberreturn "$Revision$"; }/** Should plugin be started autmatically? */bool IsSystemPlugin() { return mIsSystemPlugin; }protected:// set this to true if plugin should always be startedbool mIsSystemPlugin;};
class MainWindow;class DT_EDITQT_EXPORT PluginManager : public QObject{Q_OBJECTpublic:PluginManager(MainWindow* mw);typedef std::map<std::string,PluginFactory*> PluginFactoryMap;typedef std::map<std::string, Plugin*> ActivePluginMap;/** load all libraries in dir and check for plugin factories */void LoadPluginsInDir(const std::string& path);/** start all plugins that are saved as active in the config file */void StartPluginsInConfigFile();/*** write the list of active plugins to config file so * they can be started next time*/void StoreActivePluginsToConfigFile();/** get names of all plugins */void GetAvailablePlugins(std::list<std::string>& toFill) const;/** get names of all currently instantiated plugins */void GetActivePlugins(std::list<std::string>& toFill) const;/** is there a factory for a plugin with this name? */bool FactoryExists(const std::string& name);/** Get PluginFactory for Plugin with this name.* @throw dtUtil::Exception if no PluginFactory exists with that Plugin name* @param name The name of the Plugin/PluginFactory to get*/PluginFactory* GetPluginFactory(const std::string& name);/** is this plugin currently running? */bool IsInstantiated(const std::string& name);/** is this plugin a system plugin? */bool IsSystemPlugin(const std::string& name);/** return instance of plugin or NULL if not active */Plugin* GetPlugin(const std::string& name);/** returns all dependencies for a given plugin */std::list<std::string> GetPluginDependencies(const std::string& name);public slots:/** instantiate plugin with given name @param name Name of plugin to start@param storeToConfig Store list of active plugins to config file?*/void StartPlugin(const std::string& name, bool storeToConfig = true);/** stop and remove plugin with given name @param name Name of plugin to stop@param storeToConfig Store list of active plugins to config file?*/void StopPlugin(const std::string& name, bool storeToConfig = true);private:/** load plugin factory from library given by path */PluginFactory* LoadPluginFactory(const std::string& baseLibName);/** map from plugin name -> plugin factory */PluginFactoryMap mFactories;/** map from plugin name -> plugin instance */ActivePluginMap mActivePlugins;/** give plugins acces to GUI */MainWindow* mMainWindow;};
实现文件如下:
PluginManager::PluginManager(MainWindow* mw): mMainWindow(mw){}/** load all dlls in dir and check for plugin factories */void PluginManager::LoadPluginsInDir(const std::string& path){// find out library extension for this system// take care of debug/release library stuff on windows#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)std::string libExtension = ".dll";#elsestd::string libExtension = ".so";#endif// get libs from directoryFileExtensionList ext;ext.push_back(libExtension);DirectoryContents files;try{files = FileUtils::GetInstance().DirGetFiles(path, ext);}catch (const dtUtil::Exception& e){//in case the path is bogusDTUNREFERENCED_PARAMETER(e);}if (!files.empty()){//add the path to the list of paths to search for libraries.LibrarySharingManager::GetInstance().AddToSearchPath(path);}// for each library in dirDirectoryContents::const_iterator i;for(i = files.begin(); i != files.end(); ++i){std::string fileName = *i;try{// load the plugin libraryconst std::string basePluginName = LibrarySharingManager::GetPlatformIndependentLibraryName(fileName);PluginFactory* factory = LoadPluginFactory(basePluginName);std::string name = factory->GetName();// check if a plugin with this name already existsif(mActivePlugins.find(name) != mActivePlugins.end()){std::ostringstream msg;msg << "Unable to load plugin " << name <<": A plugin with that name was already loaded!";throw Exception(msg.str(), __FILE__, __LINE__);}// insert factory into factory listmFactories[name] = factory;// factory exists, but plugin is not instantiated yetmActivePlugins[name] = NULL;// start system plugins immediatelyif(factory->IsSystemPlugin()){StartPlugin(name, false);}}catch(Exception& e){LOG_ERROR("Can't load plugin " + (*i) + " because " + e.ToString());}}}PluginFactory* PluginManager::LoadPluginFactory(const std::string& baseLibName){// use library sharing manager to do the actual library loadingLibrarySharingManager& lsm = LibrarySharingManager::GetInstance();dtCore::RefPtr<LibrarySharingManager::LibraryHandle> libHandle;try{libHandle = lsm.LoadSharedLibrary(baseLibName, true);}catch (const Exception&){std::ostringstream msg;msg << "Unable to load plugin " << baseLibName;throw Exception(msg.str(), __FILE__, __LINE__);}LibrarySharingManager::LibraryHandle::SYMBOL_ADDRESS createFn;createFn = libHandle->FindSymbol("CreatePluginFactory");//Make sure the plugin actually implemented these functions and they//have been exported.if (!createFn){std::ostringstream msg;msg << "Plugin " << baseLibName << " does not contain symbol 'CreatePluginFactory'";throw Exception(msg.str(), __FILE__, __LINE__);}// typedef for function pointer to get factory from librarytypedef PluginFactory* (*CreatePluginFactoryFn)();// instantiate factoryCreatePluginFactoryFn fn = (CreatePluginFactoryFn) createFn;PluginFactory* factory = fn();// check if the library was compiled against this revision of STAGEif(factory->GetExpectedSTAGEVersion() != "$Revision$"){std::ostringstream msg;msg << "Can't load plugin " << baseLibName << ": Built against wrong version";throw Exception(msg.str(), __FILE__, __LINE__);}else{return factory;}}/** get the list of plugins to start from config file and start them */void PluginManager::StartPluginsInConfigFile(){dtEditQt::EditorSettings settings;settings.beginGroup(EditorSettings::ACTIVE_PLUGINS);std::string activated =settings.value(EditorSettings::ACTIVE_PLUGINS).toString().toStdString();settings.endGroup();if(activated == ""){return;}// split config string by slashesstd::vector<std::string> tokens;StringTokenizer<IsSlash>::tokenize(tokens, activated);// for each tokenstd::vector<std::string>::iterator iter;for(iter = tokens.begin(); iter != tokens.end(); ++iter){std::string name = *iter;//if the plugin can be started and was not yet startedif(FactoryExists(name) && !IsInstantiated(name)){// start it!StartPlugin(name, false);}}}/*** write the list of active plugins to config file so* they can be started next time*/void PluginManager::StoreActivePluginsToConfigFile(){// create string with names of active plugins separated by slashstd::ostringstream os;std::list<std::string> plugins;GetActivePlugins(plugins);for(std::list<std::string>::iterator i = plugins.begin(); i != plugins.end(); ++i){// system plugins are always started, so no need to include themif(!IsSystemPlugin(*i)){os << *i << "/";}}dtEditQt::EditorSettings settings;settings.beginGroup(EditorSettings::ACTIVE_PLUGINS);settings.setValue(EditorSettings::ACTIVE_PLUGINS, os.str().c_str());settings.endGroup();}PluginFactory* PluginManager::GetPluginFactory(const std::string& name){PluginFactoryMap::iterator i = mFactories.find(name);if(i == mFactories.end()){throw Exception("Plugin not found with name " + name , __FILE__, __LINE__);}return i->second;}bool PluginManager::FactoryExists(const std::string& name){return (mFactories.find(name) != mFactories.end());}void PluginManager::GetAvailablePlugins(std::list<std::string>& toFill) const{PluginFactoryMap::const_iterator iter;for(iter = mFactories.begin(); iter != mFactories.end(); ++iter){PluginFactory* factory = (*iter).second;toFill.push_back(factory->GetName());}}void PluginManager::GetActivePlugins(std::list<std::string>& toFill) const{ActivePluginMap::const_iterator iter;for(iter = mActivePlugins.begin(); iter != mActivePlugins.end(); ++iter){if((*iter).second != NULL){toFill.push_back((*iter).first);}}}std::list<std::string> PluginManager::GetPluginDependencies(const std::string& name){std::list<std::string> deps;PluginFactory* factory = GetPluginFactory(name);if (factory){factory->GetDependencies(deps);}return deps;}void PluginManager::StartPlugin(const std::string& name, bool storeToConfig){LOG_ALWAYS("Starting plugin " + name);PluginFactory* factory = GetPluginFactory(name);// start all plugins this plugin depends onstd::list<std::string> deps;factory->GetDependencies(deps);while(!deps.empty()){std::string dependency = deps.front();deps.pop_front();// check if dependency can be fulfilledif(!FactoryExists(dependency)){std::ostringstream os;os << "Cannot start plugin " << name << ": It depends on plugin ";os << dependency << " which was not found.";QMessageBox::critical(mMainWindow, "Error", os.str().c_str(), "Ok");return;}// only start dependency if it is not running nowif(!IsInstantiated(dependency)){StartPlugin(dependency, false);}}// use factory to create the pluginmActivePlugins[name] = factory->Create(mMainWindow);// call Create() callback of pluginmActivePlugins[name]->Create();}void PluginManager::StopPlugin(const std::string& name, bool storeToConfig){// first check if plugin is actually runningif(!IsInstantiated(name)){return;}// Check if any other plugins depend on this one, and stop them as well.std::list<std::string> activePlugins;GetActivePlugins(activePlugins);while(!activePlugins.empty()){std::string plugin = activePlugins.front();activePlugins.pop_front();PluginFactory* factory = GetPluginFactory(plugin);// start all plugins this plugin depends onstd::list<std::string> deps;factory->GetDependencies(deps);while(!deps.empty()){std::string dependency = deps.front();deps.pop_front();// If the active plugin depends on this plugin, then we need to stop that one too.if (dependency == name){StopPlugin(plugin);break;}}}LOG_ALWAYS("Stopping plugin " + name);Plugin* plugin = GetPlugin(name);// call Destroy() callback of pluginplugin->Destroy();// tell factory to delete the pluginGetPluginFactory(name)->Destroy();// erase plugin from list of active pluginsmActivePlugins.erase(mActivePlugins.find(name));}bool PluginManager::IsInstantiated(const std::string& name){// all plugin names are in mActivePlugins, but names of non-active plugins// are mapped to NULLreturn mActivePlugins[name] != NULL;}/** is the plugin a system plugin? */bool PluginManager::IsSystemPlugin(const std::string& name){return GetPluginFactory(name)->IsSystemPlugin();}Plugin* PluginManager::GetPlugin(const std::string& name){// first check if plugin exists. return NULL if it doesn'tActivePluginMap::iterator i = mActivePlugins.find(name);if(i == mActivePlugins.end()){return NULL;}return i->second;}

通过继承自抽象类Plugin实现自定义的插件,同时继承自PluginFactory重写主要函数实现自定义插件工厂(负责插件的生成),可以方便的对UI进行扩展;

 /** construct the plugin and return a pointer to it */virtual Plugin* Create(MainWindow* mw) = 0;/** delete the plugin */virtual void Destroy() = 0;/** get the name of the plugin */virtual std::string GetName() = 0;/** get a description of the plugin */virtual std::string GetDescription() = 0;


自定义插件实现如下:

class XX_EXPORT CustomPlugin : public Plugin
{
public :void Create(){};void Destroy(){};
};
public XX_EXPORT CustomPluginFactory :public PluginFactory
{public :
Plugin* Create(MainWindow* mw)
{   mPlugin = new CustomPlugin(mv);return mPlugin;
}void Destory()
{delete mPlugin;
}private:Plugin* mPlugin;
};

在Dll中导出全局函数:

extern "C" XX_EXPORT PluginFactory* CreatePluginFactory()
{return new PluginFactory();
}




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中泛型学习总结

为什么需要使用泛型: 1):存储任意类型的数据在集合中 ,但是取出来都是Object类型的,此时就得强转.List list new ArrayList();list.add(1); //Interger类型Object ele list.get(0); //现在需要调用Interger类中的方法I nterger num (Interger) ele;System.out.println(num);…

数据结构实验之栈:行编辑器

题目描述 一个简单的行编辑程序的功能是&#xff1a;接受用户从终端输入的程序或数据&#xff0c;并存入用户的数据区。 由于用户在终端上进行输入时&#xff0c;不能保证不出差错&#xff0c;因此&#xff0c;若在编辑程序中&#xff0c;“每接受一个字符即存入用户数据区”的…

CDH、CM下载403,Cloudera收费无法下载解决,CDH安装包下载

CDH下载 6.3.2 链接: https://pan.baidu.com/s/1e1LmRY7aHQSCMJq3Lz6DtA 密码: 1vje --来自百度网盘超级会员V6的分享6.3.1 链接: https://pan.baidu.com/s/1Xsj_zDvuJ12q3pGTY77BRg 密码: f9h3 --来自百度网盘超级会员V6的分享6.2.1 链接: https://pan.baidu.com/s/10s7…

别说“我已经很努力了”

转自&#xff1a;http://blog.csdn.net/foruok/article/details/40247543 我们程序员的努力与挣扎有时非常尴尬&#xff0c;如果没有结果&#xff0c;都是徒然&#xff0c;都是说不得说不得…… 我自己做项目经理时&#xff0c;干的项目也经常延期……非常惭愧。而延期其实对研…

Java集合框架-概述

Java集合框架的由来: 其实在Java2(jdk1.2)之前&#xff0c;Java是没有完整的集合框架的。它只有一些简单的可以自扩展的容器类&#xff0c;比如Vector&#xff0c;Stack&#xff0c;Hashtable等。 为什么存在容器类: 容器类(集合类)可以存储多个数据,既然数组可以存储多个数据…

MySQL Binlog增量同步工具go-mysql-transfer实现详解

go-mysql-transfer产品手册:https://www.kancloud.cn/wj596/go-mysql-transfer/2111996 一、 概述 工作需要研究了下阿里开源的MySQL Binlog增量订阅消费组件canal&#xff0c;其功能强大、运行稳定&#xff0c;但是有些方面不是太符合需求&#xff0c;主要有如下三点&#x…

数据结构实验之栈五:下一较大值(一)

题目描述 对于包含n&#xff08;1<n<1000&#xff09;个整数的序列&#xff0c;对于序列中的每一元素&#xff0c;在序列中查找其位置之后第一个大于它的值&#xff0c;如果找到&#xff0c;输出所找到的值&#xff0c;否则&#xff0c;输出-1。 输入 输入有多组&#xf…

与 C++11 多线程相关的头文件

C11 新标准中引入了四个头文件来支持多线程编程&#xff0c;他们分别是<atomic> ,<thread>,<mutex>,<condition_variable>和<future>。 <atomic>&#xff1a;该头文主要声明了两个类, std::atomic 和 std::atomic_flag&#xff0c;另外还…

数据结构实验之栈二:一般算术表达式转换成后缀式

题目描述 对于一个基于二元运算符的算术表达式&#xff0c;转换为对应的后缀式&#xff0c;并输出之。输入 输入一个算术表达式&#xff0c;以‘#’字符作为结束标志。输出 输出该表达式转换所得到的后缀式。示例输入 a*b(c-d/e)*f# 示例输出 ab*cde/-f* #include<stdio.h…

INFINI GATEWAY 极限网关初体验 ElasticSearch 两个集群数据同步

文章目录极限网关-配置说明配置文件日志、数据目录定义入口定义路由定义流程定义资源使用Demo写入两个ES集群极限网关-常见问题shutdown: ORM handler is not registered极限网关地址极限网关-配置说明 极限网关的大部分配置都可以通过 gateway.yml 来进行配置&#xff0c;配置…

std::thread详解

转自&#xff1a;http://www.cnblogs.com/haippy/p/3236136.html 上一篇博客《C11 并发指南一(C11 多线程初探)》中只是提到了 std::thread 的基本用法&#xff0c;并给出了一个最简单的例子&#xff0c;本文将稍微详细地介绍 std::thread 的用法。 std::thread 在 <thread&…

Kafka 详细配置参数说明

参数值参数文件描述auto.create.topics.enableserver.properties【说明】是否允许自动创建Topic&#xff0c;若是false&#xff0c;就需要通过命令创建Topic。【默认值】true【取值范围】true或falselog.cleaner.backoff.msserver.properties【说明】检查是否有日志需要清理的时…

数据结构实验之栈三:后缀式求值

题目描述 对于一个基于二元运算符的后缀表示式&#xff08;基本操作数都是一位正整数&#xff09;&#xff0c;求其代表的算术表达式的值。输入 输入一个算术表达式的后缀式字符串&#xff0c;以‘#’作为结束标志。输出 求该后缀式所对应的算术表达式的值&#xff0c;并输出之…

std::mutex详解

Mutex 又称互斥量&#xff0c;C 11中与 Mutex 相关的类&#xff08;包括锁类型&#xff09;和函数都声明在 <mutex> 头文件中&#xff0c;所以如果你需要使用 std::mutex&#xff0c;就必须包含 <mutex> 头文件。 <mutex> 头文件介绍 Mutex 系列类(四种) st…

java中stack集合框架

栈(Stack):数据结构的一种,存储特点:Last In First Out. Stack 类表示后进先出&#xff08;LIFO&#xff09;的对象栈. 栈结构在生活中的体现: 1):QQ消息. A,B,C三个人先后发送消息,我们查看的时候发现最顶上的是最新的消息. 2):手枪弹夹的装和发射: 要来实现栈的存储,底层…

ElasticSearch Pipeline 为新增数据设置更新时间

文章目录模拟测试测试返回结果实际应用创建Pipeline查看创建Pipeline新增数据测试查看新增数据创建索引时直接设置Pipeline模拟测试 测试 POST _ingest/pipeline/_simulate {"pipeline": {"processors": [{"set": {"field": "t…

队列的基本操作

链式存储 typedef int QElemType; typedef int Status;//具体数据类型具体定义 typedef struct QNode//队列结点结构体 { QElemType data; QNode *next; } QNode, *Queueptr; typedef struct // 链队列类型 { Queueptr front; // 队头指针&#xff08;结构体类…

c++阻塞队列

基于C11的阻塞队列简单实现 转载请说明出处&#xff1a;http://blog.csdn.net/cywosp/article/details/9157379 在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区别在于&#xff0c;当队列为空时&#xff0c;从队列获取…

java中ArrayList类的操作

ArrayList类是Java集合框架出现之后用来取代Vector类的: 二者底层原理都是基于数组的算法,一模一样. 区别: Vector: 所有的方法都使用了synchronized修饰符. 线程安全但是性能较低. 适用于多线程环境. ArrayList:所有的方法都没有使用synchronized修饰符. 线程不安全但是性…

Elasticsearch Painless Script详解

文章目录1. Painless 简介Painless 的用途2. 参数3. 首选参数4. 简短脚本形式5. 通过 Painless 脚本访问字段6. 示例6.1 案例 1&#xff1a;Script Processsor6.2 案例 2&#xff1a;文档更新计数6.3 案例 3&#xff1a;搜索时的 Script 字段6.4 Script :Inline v.s Stored6.5 …