codeblocks中plugin的实现

快乐虾 http://blog.csdn.net/lights_joy/ lights@hb165.com

本文适用于

codeblocks-8.02

vs2005

 

 

 

1.1     Plugin 加载

Codeblocksplugin 放在可执行文件目录下的 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.xmlconfiguration.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 时,它应该能够调用 RegisterPlugincodeblock 进行注册,下面以 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 为例进行分析。 Codeblocksplugin 分为几类:

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

};

呵呵,看着好像挺简单的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值