codeblocks中plugin的实现

80 篇文章 1 订阅
13 篇文章 0 订阅

快乐虾

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

};

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

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值