CodeLite Plugin Internal(2)-Load: 插件加载分析
上回书说到IPlugin接口和众插件之间的关系,这里讲讲插件加载的过程。加载点在系统初始化时Framezhong 调用,上次也说过。这里主要是从PluginManager::Load() 说起。首先读取插件配置文件 config/plugins.xml,并将信息保存到std::map<wxString, PluginInfo> m_pluginsInfo中,这个成员m_pluginsInfo是属于PluginManager,这个map保存了插件名称和Pluginfo的映射关系。接着TagManagerST和LanguageST互相赋值。
现在进入重点循环,针对插件目录下的每个.dll/.so文件,会进行1)加载动态库;2)读插件信息;3)加载插件;4)调用插件相关创建toolbar和menu的函数。下面一一详述:
1)加载动态库:主要是通过clDynamicLibrary类,该类调用wxDynamicLibrary功能实现对动态链接库的加载,load();
clDynamicLibrary *dl = new clDynamicLibrary();
wxString fileName( files.Item( i ) );
if ( !dl->Load( fileName ) ) {
wxLogMessage( wxT( "Failed to load plugin’s dll: " ) + fileName );
if (!dl->GetError().IsEmpty())
wxLogMessage(dl->GetError());
delete dl;
continue;
}
2)读插件信息:还是wxDynamicLibrary的GetSymbol获得插件的函数指针GET_PLUGIN_INFO_FUNC和GET_PLUGIN_INTERFACE_VERSION_FUNC,并调用相应函数获取插件信息和接口版本号;
GET_PLUGIN_INFO_FUNC pfnGetPluginInfo = ( GET_PLUGIN_INFO_FUNC )dl->GetSymbol( wxT( "GetPluginInfo" ), &success );
if ( !success ) {
wxLogMessage(wxT("Failed to find GetPluginInfo in dll: ") + fileName);
if (!dl->GetError().IsEmpty())
wxLogMessage(dl->GetError());
delete dl;
continue;
}// load the plugin version method
// if the methods does not exist, handle it as if it has value of 100 (lowest version API)
int interface_version(100);
GET_PLUGIN_INTERFACE_VERSION_FUNC pfnInterfaceVersion = (GET_PLUGIN_INTERFACE_VERSION_FUNC) dl->GetSymbol(wxT("GetPluginInterfaceVersion"), &success);
if ( success ) {
interface_version = pfnInterfaceVersion();
} else {
wxLogMessage(wxT("Failed to find GetPluginInterfaceVersion() in dll: ") + fileName);
if (!dl->GetError().IsEmpty())
wxLogMessage(dl->GetError());
}if ( interface_version != PLUGIN_INTERFACE_VERSION ) {
wxLogMessage(wxString::Format(wxT("Version interface mismatch error for plugin ‘%s’. Plugin’s interface version is ‘%d’, CodeLite interface version is ‘%d’"),
fileName.c_str(),
interface_version,
PLUGIN_INTERFACE_VERSION));
delete dl;
continue;
}
3)故技重实,通过GetSymbol获得插件的CreatePlugin函数:
GET_PLUGIN_CREATE_FUNC pfn = ( GET_PLUGIN_CREATE_FUNC )dl->GetSymbol( wxT( "CreatePlugin" ), &success );
通过调用该函数加载并初始化插件,可见每个插件都必须实现这个CreatePlugin函数并export出来。
4)调用CreatePlugin之后,我们就得到IPlugin指针代表了这个插件实例(这个看起来很熟悉吧,不熟悉请参考前一篇IPlugin文章)
IPlugin *plugin = pfn( ( IManager* )this );之后就是想当然的调用plugin->CreateToolBar( Frame::Get() );创建工具条,和plugin->CreatePluginMenu( pluginsMenu );创建相应菜单。
循环结束后,最后一件事就是保存插件信息:
PluginsData pluginsData;
pluginsData.SetInfo(actualPlugins);
PluginConfig::Instance()->WriteObject(wxT("plugins_data"), &pluginsData);
插件加载结束了,如有任何疑问请联系Bryan Wu (cbforge at gmail.com),转载也请注明出处: cbforge.com,Bryan Wu. 2009.
Happy Children’s Day to DuoDuo!
Related posts:
- CodeLite Plugin Internal(1) – IPlugin interface
- Code::Blocks中Plugin的实现原理
- CodeLite Initializaion analysis - 初始化流程分析(1)
- CodeLite IDE介绍
- C::B IDE Plugin插件简介
- Codelite代码分析之 Singleton Pattern Template实现及应用
- CodeLite to CodeInsight task 1: Internationalization
- CodeLite 编译解析(with Compile log)
- Debugging With CodeLite - CodeLite调试简介
- Using XRC in wxWidgets based Application for UI design














