![]() |
|
||||||||||||||
| | 首页 | 新闻 | 文库 | 方案 | 技术 | 独家 | 座谈 | 下载 | 图库 | 开发板 | 仿真器 | 邮购 | VIP | 芯片 | 客户评价 | 论坛 | | ||
|
||
|
|||||
| codeblocks中plugin的实现 | |||||
作者:快乐虾 文章来源:http://blog.csdn.net/lights_joy 点击数: 更新时间:2008-9-10 ![]() |
|||||
1.1 Plugin加载Codeblocks将plugin放在可执行文件目录下的share\CodeBlocks\plugins子目录中,全部以DLL的形式存在。在codeblock启动时会调用如下函数: int PluginManager::ScanForPlugins(const wxString& path) { ………………………………….. wxDir dir(path); wxString filename; wxString failed; bool ok = dir.GetFirst(&filename, PluginsMask, wxDIR_FILES); while (ok) { ……………………. // load manifest m_pCurrentlyLoadingManifestDoc = 0; if (ReadManifestFile(filename)) { if (LoadPlugin(path + _T('/') + filename)) ++count; else failed << _T('\n') << filename; } delete m_pCurrentlyLoadingManifestDoc; m_pCurrentlyLoadingManifestDoc = 0; ok = dir.GetNext(&filename); } ………………………………….. } 在上述代码中,将首先读取与dll同名的manifest,其实它就是一个放在share/codeblocks子目录下的同名zip文件,这个zip文件中两个文件:manifest.xml和configuration.xrc,其实这两个文件都是XML文档,manifest.xml描述了这个插件的功能,作者等信息,而另一个文件则是一些配置信息。 在读取manifest成功后将调用LoadPlugin函数: bool PluginManager::LoadPlugin(const wxString& pluginName) { // clear registration temporary vector m_RegisteredPlugins.clear(); // load library m_CurrentlyLoadingFilename = pluginName; m_pCurrentlyLoadingLib = LibLoader::LoadLibrary(pluginName); if (!m_pCurrentlyLoadingLib->IsLoaded()) { Manager::Get()->GetLogManager()->LogError(F(_T("%s: not loaded (missing symbols?)"), pluginName.c_str())); LibLoader::RemoveLibrary(m_pCurrentlyLoadingLib); m_pCurrentlyLoadingLib = 0; m_CurrentlyLoadingFilename.Clear(); return false; } // by now, the library has loaded and its global variables are initialized. // this means it has already called RegisterPlugin() // now we can actually create the plugin(s) instance(s) :) // try to load the plugin(s) std::vector<PluginRegistration>::iterator it; for (it = m_RegisteredPlugins.begin(); it != m_RegisteredPlugins.end(); ++it) { PluginRegistration& pr = *it; cbPlugin* plug = try { plug = pr.createProc(); } catch (cbException& exception) { exception.ShowErrorMessage(false); continue; } // all done; add it to our list PluginElement* plugElem = new PluginElement; plugElem->fileName = m_CurrentlyLoadingFilename; plugElem->info = pr.info; plugElem->library = m_pCurrentlyLoadingLib; plugElem->freeProc = pr.freeProc; plugElem->plugin = plug; m_Plugins.Add(plugElem); SetupLocaleDomain(pr.name); Manager::Get()->GetLogManager()->DebugLog(F(_T("%s: loaded"), pr.name.c_str())); } if (m_RegisteredPlugins.empty()) { // no plugins loaded from this library, but it's not an error LibLoader::RemoveLibrary(m_pCurrentlyLoadingLib); } m_pCurrentlyLoadingLib = 0; m_CurrentlyLoadingFilename.Clear(); return true; } 这个函数首先调用LibLoader::LoadLibrary加载DLL,实际上它就是使用LoadLibrary这个API来加载DLL。 在加载完成后,按照注释的说明,这个DLL中应该调用RegisterPlugin函数进行自我注册,这其中当然包括创建实例这样回调函数,然后上述函数很自然地使用这样的回调函数创建Plugin的实例。然后用一个PluginElement来描述它,这个plugElem将用于主界面的菜单等位置。 从上述代码还可以看出,插件至少应该能创建一个cbPlugin的实例。 1.2 插件注册从调用过程的注释可以知道,在加载DLL时,它应该能够调用RegisterPlugin向codeblock进行注册,下面以astyle这个插件为例看看它的注册过程。 在这个插件中定义了一个全局变量: namespace { PluginRegistrant<AStylePlugin> reg(_T("AStylePlugin")); } 除此之外没有其它东西可以在DLL加载时执行代码,看看PluginRegistrant这个类: /** @brief Plugin registration object. * * Use this class to register your new plugin with Code::Blocks. * All you have to do is instantiate a PluginRegistrant object. * @par * Example code to use in one of your plugin's source files (supposedly called "MyPlugin"): * @code * namespace * { * PluginRegistrant<MyPlugin> registration("MyPlugin"); * } * @endcode */ template<class T> class PluginRegistrant { public: /// @param name The plugin's name. PluginRegistrant(const wxString& name) { Manager::Get()->GetPluginManager()->RegisterPlugin(name, // plugin's name &CreatePlugin, // creation &FreePlugin, // destruction &SDKVersion); // SDK version } static cbPlugin* CreatePlugin() { return new T; } static void FreePlugin(cbPlugin* plugin) { delete plugin; } static void SDKVersion(int* major, int* minor, int* release) { if (major) *major = PLUGIN_SDK_VERSION_MAJOR; if (minor) *minor = PLUGIN_SDK_VERSION_MINOR; if (release) *release = PLUGIN_SDK_VERSION_RELEASE; } }; 由此可见,在主程序加载DLL后还将调用PluginRegistrant ::CreatePlugin这个回调函数,而这个回调函数将创建一个AStylePlugin的实例。 1.3 Plugin功能实现仍以astyle为例进行分析。Codeblocks将plugin分为几类: cbCompilerPlugin cbDebuggerPlugin cbToolPlugin cbMimePlugin cbCodeCompletionPlugin cbWizardPlugin astyle要完成代码格式化的功能,因而它选择了cbToolPlugin进行扩展: class AStylePlugin : public cbToolPlugin { public: AStylePlugin(); ~AStylePlugin(); int Configure(); int GetConfigurationGroup() const { return cgEditor; } cbConfigurationPanel* GetConfigurationPanel(wxWindow* parent); int Execute(); void OnAttach(); // fires when the plugin is attached to the application void OnRelease(bool appShutDown); // fires when the plugin is released from the application }; 呵呵,看着好像挺简单的。 |
|||||
| 文章录入:admin 责任编辑:admin | |||||
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 | |||||
| 网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!) |
| | 本站介绍 | 合作联络 | 欢迎投稿 | 广告业务 | 网站地图 | 设为首页 | 加入收藏 | 友情链接 | 网站公告 | 联系我们 | | |||
|