首页 > 未分类 > REDM基础教程21-插件机制
2018十月20

REDM基础教程21-插件机制

[隐藏]

DM的插件中install一般封装的是注册机制

g_pDMApp->Register(DMRegHelperT<xxxx>(),true);

   

1.基本原理

   

插件的基本实现原理流程如下:

插件加载器通过外部dll接口内部加载两种模式, IDMPlugin对象加入到内部队列中。

IDMPlugin提供了加载、初始化、反初始化、卸载四个接口函数,插件加载器在不同的时机, 会遍历它内部IPlugin对象队列并调用对应的接口函数。

IDMPlugin的接口函数内部一般封装了扩展代码,例如:在加载接口函数中,扩展实现一个LOG写入到文件类, 并通过注册管理器注册到内部, 替换掉内部原始的LOG打印输出类。   

image.png

  

1.1.内部加载

  

直接内部调用:

theApp.InstallPlugin(IDMPlugin对象)

  

1.2.外部dll接口

   

外部的dll插件必须有如下两个固定的导出函数, 在加载、卸载外部dll插件时分别被调用。

dllStartPlugin函数一般所做的操作是调用InstallPlugin安装dll内所有的自实现IDMPlugin对象。

dllStopPlugin函数一般所做的操作是调用UninstallPlugin卸载dll内所有的自实现IDMPlugin对象。

image.png

  

通过LoadPlugin加载外部dll插件流程如下:

image.png

可以看到,LoadPlugin最终是调用了IDMPlugin::install函数

   

DM也封装了另一个LoadPlugins接口, 通过Xml解析遍历加载外部dll插件列表

  


2.Plugin_Expand插件示例

   

1.Plugin_Expand\src\Plugin_ExpandExp.cpp导出了dllStartPlugin和dllStopPlugin接口,它们所做的工作是加载和卸载IDMPlugin,代码如下:

static Plugin_Expand* plugin;
extern "C"
void PLUGINEXPAND_EXPORTS dllStartPlugin(void) throw()
{
	plugin = new Plugin_Expand();
	DMApp::getSingleton().InstallPlugin(plugin);
}

extern "C"
void PLUGINEXPAND_EXPORTS dllStopPlugin(void)
{
	DMApp::getSingleton().UninstallPlugin(plugin);
	delete plugin;
}

  

2.Plugin_Expand是IDMPlugin的实现体。

class Plugin_Expand:public IDMPlugin
{
public:
	Plugin_Expand(void);
	~Plugin_Expand(void);

	const wchar_t* GetName() const;
	void Install();
	void Uninstall();

	void Initialise();
	void Shutdown();

};

  

3.由前面的框架图可知

DMApp::getSingleton().InstallPlugin(plugin);

最终调用的是:

void Plugin_Expand::Install()
{
	g_pDMApp->Register(DMRegHelperT<DM3DAnimate>(),true);
	g_pDMApp->Register(DMRegHelperT<DMLineAnimate>(),true);
	g_pDMApp->Register(DMRegHelperT<DMScreenAnimate>(),true);
	g_pDMApp->Register(DMRegHelperT<DMResZipImpl>(),true);
	g_pDMApp->Register(DMRegHelperT<DMResMultZipImpl>(),true);
#ifdef USE_DMSKIA_RENDER_
	DMCode iErr = g_pDMApp->Register(DMRegHelperT<DMSkiaRenderImpl>(),true);
	DMASSERT_EXPR(DMSUCCEEDED(iErr), L"注册DMSkiaRenderImpl失败!");
	iErr = g_pDMApp->SetDefRegObj(DMSkiaRenderImpl::GetClassName(),DMSkiaRenderImpl::GetClassType());
	DMASSERT_EXPR(DMSUCCEEDED(iErr), L"设置DMSkiaRenderImpl为默认Render对象失败!");
#endif
}

这里做了什么呢?参考前一节注册类机制,它加入了3D特效、skia绘制引擎、zip打包Res资源、多zip打包Res资源、

   

我们来看下DMDemo中使用Plugin_Expand的3D特效吧:(你可以试着删除Plugin_Expand_d/Plugin_Expand.dll,3D特效就会无效)

21.gif

   

2.1.怎么安装插件

  

DMDemo\src\DMDemo.cpp中:

theApp.LoadPlugins(L"dmpluginsd.cfg");

 

而dmpluginsd.cfg的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<body>
	<!--directory指明了plugin存放在哪个文件夹内,相对于exe路径-->
	<directory name="..\plugins\">
		<item name="Plugin_Expand_d"/>
	</directory>
</body>

   

directory可以指定多个,以加载不同文件夹下的dll,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<body>
	<!--directory指明了plugin存放在哪个文件夹内,相对于exe路径-->
	<directory name="..\plugins1\">
		<item name="A"/>
		<item name="B"/>
	</directory>
        <directory name="..\plugins2\">
		<item name="C"/>
		<item name="D"/>
	</directory>
</body>

 

当然,你也可以简单粗暴的使用:

theApp.LoadPlugin("d:\\Plugin_Expand.dll");

  


2.2.skia绘制引擎

  

skia的优势是绘制速度快,缺点是体积较大,minsizerel大约1M左右

  

1.cmake中勾选开启USE_SKIA_宏,也就是代码中增加了USE_DMSKIA_RENDER_宏

image.png

void Plugin_Expand::Install()
{
        ...
#ifdef USE_DMSKIA_RENDER_
	DMCode iErr = g_pDMApp->Register(DMRegHelperT<DMSkiaRenderImpl>(),true);
	DMASSERT_EXPR(DMSUCCEEDED(iErr), L"注册DMSkiaRenderImpl失败!");
	iErr = g_pDMApp->SetDefRegObj(DMSkiaRenderImpl::GetClassName(),DMSkiaRenderImpl::GetClassType());
	DMASSERT_EXPR(DMSUCCEEDED(iErr), L"设置DMSkiaRenderImpl为默认Render对象失败!");
#endif
}

   

2.加载Plugin_Expand插件即可,如果你不想要其他注册,就把它们删除掉即可。

     

对于插件里的注册类,你可以抽离出来,比如放在你的exe代码中,然后调用g_pDMApp->Register(DMRegHelperT<xxxx>(),true);

   

2.3.zip打包Res资源

  

参看http://hgy413.com/3830.html

或者在Plugin_Expand::Install()中加入:

g_pDMApp->SetDefRegObj(DMResZipImpl::GetClassName(),DMResZipImpl::GetClassType());// 把zip打包设置为默认

或者

g_pDMApp->SetDefRegObj(DMResMultZipImpl::GetClassName(),DMResZipImpl::GetClassType());// 把多zip打包设置为默认

文章作者:hgy413
本文地址:http://hgy413.com/5320.html
版权所有 © 转载时必须以链接形式注明作者和原始出处!

本文的评论功能被关闭了.