codeblocks中plugin的实现方法

2008-09-10 15:03:28 来源:中国自学编程网 作者: 点击:
Codeblocks将plugin放在可执行文件目录下的share\CodeBlocks\plugins子目录中,全部以DLL的形式存在。在codeblock启动时会调用如下函数:



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 = 0L;

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"):
9 7 3 1 2 4 8 :



本类最新行业评测技巧教程学院
本类热点本日本周本月
本类推荐本日本周本月

广告联系 | 版权说明 | 意见建议 | 加入收藏 | 军网站群 [ 军软件园 - 军软件商城 - 军软件园论坛 ]

电信与信息服务业务经营许可证:京ICP证050203