你的位置:m6米乐在线客服(中国)有限公司 > 联系我们 > 米乐m6平台官方版 聊聊Pluma插件搞定框架

米乐m6平台官方版 聊聊Pluma插件搞定框架

时间:2022-09-23 12:38 点击:105 次

米乐m6平台官方版 聊聊Pluma插件搞定框架

开头 | OSCHINA 社区

作家 | 逍遥红茶-侯亮

1. 综合

Pluma 是一个用 C++ 诞生的可用于搞定插件的开源架构,其官网地址为:http://pluma-framework.sourceforge.net/。该架构是个轻量级架构,特出易于意会。

Pluma 架构有以下基本成见:

1)插件的外皮活动体现为一个纯虚类,不错叫作插件接口;

2)罗致于归拢个插件接口的多少派生类,被觉得属于归拢种插件,不错叫作插件类;

3)每一个插件接口或插件类都有个逐一双应的 Provider 类,其中,插件接口对应的 Provider 类里会界说一个异常字符串常量:PLUMA_PROVIDER_TYPE,露出这一类 “插件 Provider” 共同的类型称呼,而这个类型称呼其实等于插件接口的类名字符串。

4)多个插件类不错被放入一个插件动态库中,而这个动态库文献名(不包括后缀部分)不错叫作 “插件名”。

5)插件机制使用者不错在我方的架构中包含一个 Pluma 搞定类,该类撑持从所指定的位置加载一个或多个插件动态库,并将每个插件类对应的 Provider,记载进里面的表中。

6)插件机制使用者不错在合应时机,哄骗 Pluma 取得内含的插件 Provider,并调用某个插件 Provider 的 create 函数,创建出对应的插件对象。

7)使用完插件对象后,不要忘了 delete 它。

目下咱们画一张暗意图:

2. Pluma 搞定类

咱们刚刚也说了,插件机制使用者不错包含一个 Pluma 搞定类。该类罗致于 PluginManager 类。

【pluma-1.1/include/pluma/PluginManager.hpp】

protected: PluginManager;voidregisterType( conststd:: string& type, unsignedintversion, unsignedintlowestVersion) ; conststd:: list<Provider*>* getProviders( conststd:: string& type) const;

private: staticstd:: stringgetPluginName( conststd:: string& path) ; staticstd:: stringresolvePathExtension( conststd:: string& path) ;

private: typedefboolfnRegisterPlugin(Host&); typedefstd:: map< std:: string,DLibrary*> LibMap;

LibMap libraries; ///< Map containing the loaded librariesHost host; ///< Host app proxy, holding all providers};

从上头的 load 函数和 loadFromFolder 函数不错看出,插件搞定器既允许用户单独加载某个插件动态库,也允许批量性加载某个目次下通盘的插件动态库。另外,值得看重的是,getProviders 函数是 protected 的成员,也等于说,这套架构是不但愿用户平直使用这个 PluginManager 类的,即便用了,你也拿不到 Provider。正确的做法是,使用 PluginManager 的子类:Pluma 搞定类。

另外,上头的成员变量 libraries,等于记载通盘已加载的插件动态库的映射表。而成员变量 host 则认真记载每个插件类对应的 Provider 信息。之是以被称为 host(宿主),是针对插件而言的。也等于说插件本身实质上是没履历走漏其确切宿主的全貌的,它只可窥察和它研讨的很小一部分数据费力,因此 Pluma 将这一小部分数据整理成一个 host 代理,供插件使用。 Pluma 搞定类的代码截选如下:

【pluma-1.1/include/pluma/Pluma.hpp】

template< typenameProviderType> voidacceptProviderType;

template< typenameProviderType> voidgetProviders( std:: vector<ProviderType*>& providers) ; };

# include<Pluma/Pluma.inl>

请民众看重上头代码中终末一滑,这个 Pluma.hpp 还真实有点手黑,暗暗摸摸 #include 了个 Pluma.inl 文献,其实伸开来等于 acceptProviderType 和 getProviders 这两个模板函数的扫尾。Pluma.inl 文献的内容如下:

【pluma-1.1/include/pluma/Pluma.inl】

template< typenameProviderType> voidPluma::acceptProviderType{ PluginManager::registerType(ProviderType::PLUMA_PROVIDER_TYPE,ProviderType::PLUMA_INTERFACE_VERSION,ProviderType::PLUMA_INTERFACE_LOWEST_VERSION);}

template< typenameProviderType> voidPluma::getProviders( std:: vector<ProviderType*>& providers){ conststd:: list<Provider*>* lst = PluginManager::getProviders(ProviderType::PLUMA_PROVIDER_TYPE);if(!lst) return; providers.reserve(providers.size + lst->size);std:: list<Provider*>::const_iterator it; for(it = lst->begin ; it != lst->end ; ++it) providers.push_back( static_cast<ProviderType*>(*it)); }

看到了吧,重新界说了个 getProviders ,还搞成一个模板函数,在函数体内会反过来通过模板参数,进一步得到所波及的插件 Provider 的 PLUMA_PROVIDER_TYPE 信息,这个技能挺伏击。也等于说,外界传来的是 vector<ProviderType>,而函数里面不错测度出 ProviderType::PLUMA_PROVIDER_TYPE。将 PLUMA_PROVIDER_TYPE 传入父类的 PluginManager::getProviders 函数,就不错拿到允洽所指类型的通盘 Provider。

咱们画一张 Pluma 简图,背面再细说研讨细节:

归拢类插件类,会对应一个 ProviderInfo 节点,该节点里面的 providers 列表,记载着同属一类的多少 Provider。

2.1 Host 代理

【pluma-1.1/include/pluma/Host.hpp】

public: booladd(Provider* provider);

private: Host;~Host;boolknows( conststd:: string& type) const; unsignedintgetVersion( conststd:: string& type) const; unsignedintgetLowestVersion( conststd:: string& type) const; voidregisterType( conststd:: string& type, unsignedintversion, unsignedintlowestVersion) ; conststd:: list<Provider*>* getProviders( conststd:: string& type) const; voidclearProviders; boolvalidateProvider(Provider* provider)const; boolregisterProvider(Provider* provider); voidcancelAddictions; boolconfirmAddictions;

private: structProviderInfo{ unsignedintversion; unsignedintlowestVersion; std:: list<Provider*> providers; };typedefstd:: map< std:: string, ProviderInfo > ProvidersMap; typedefstd:: map< std:: string, std:: list<Provider*> > TempProvidersMap;

ProvidersMap knownTypes; ///< Map of registered types.TempProvidersMap addRequests; ///< Temporarily added providers};

正如前文所说,Host 代理是针对插件而言的。而 Host 唯唯一个 public 成员函数 add ,诠释其主要对生手为等于让插件将对应的 provider 注册进 Host。

3. 插件类和其对应的 Provider 类

在说了一大堆插件搞定类代码后,目下终于要开动说插件部分了。前文依然说过,插件的外皮活动体现为一个纯虚类,不错叫作插件接口。咱们目下就以 Pluma 源码中给出的例子为准,来诠释一些细节。

3.1 Warrior 接口和 WarriorProvider 类

Pluma 中的插件接口例子是 Warrior,其源码截选如下:

【pluma-1.1/example/src/interface/Warrior.hpp】

这个接口里只记号性的写了一个成员函数 getDeion ,民众认识风趣即可。

需要看重的是类界说之后的那句 PLUMA_PROVIDER_HEADER,这个宏认真界说和插件接口对应的 Provider 类。研讨的宏界说如下:

【pluma-1.1/include/pluma/Pluma.hpp】

#define PLUMA_PROVIDER_HEADER_BEGIN(TYPE)\classTYPE ##Provider: public pluma::Provider{\private:\friend classpluma::Pluma;\ staticconstunsignedintPLUMA_INTERFACE_VERSION;\ staticconstunsignedintPLUMA_INTERFACE_LOWEST_VERSION;\ staticconststd::string PLUMA_PROVIDER_TYPE;\ std::string plumaGetType const{ returnPLUMA_PROVIDER_TYPE; }\ public:\unsignedintgetVersion const{ returnPLUMA_INTERFACE_VERSION; }

#define PLUMA_PROVIDER_HEADER_END };

基于这些宏界说,咱们不错将 PLUMA_PROVIDER_HEADER (Warrior) 伸开为:

代码很显著,为 Warrior 接口声明一个配套的 WarriorProvider 类。这个类里包含着伏击的 PLUMA_PROVIDER_TYPE 常量,以及最要津的 create 函数。

Warrior 的扫尾文献愈加通俗:

【pluma-1.1/example/src/interface/Warrior.cpp】

也在使用宏,伸开宏后可见:

因为 Warrior 本身是个纯虚类,是以 WarriorProvider 里也不必扫尾 create 函数。

3.2 Warrior 派生类和派生 Provider

在 pluma 源码的例子中,提供了三个 Warrior 派生类,SimpleWarrior、Eagle 和 Jaguar。默许的是 SimpleWarrior,它被集成进 example/src/host 目次。也等于说,即便咱们一个突出的插件库都不提供,示例至少还不错使用 SimpleWarrior。而 Eagle 和 Jaguar 则位于 example/src/plugin 目次,联系我们不错打包进一个插件动态库。

【pluma-1.1/example/src/host/SimpleWarrior.hpp】

前文咱们依然看到,关于插件接口(Warrior)来说,用到的宏是 PLUMA_PROVIDER_HEADER(Warrior),目下针对实质插件类(SimpleWarrior),会用到另一个宏 PLUMA_INHERIT_PROVIDER(SimpleWarrior, Warrior)。这个宏的界说如下:

【pluma-1.1/include/pluma/Pluma.hpp】

伸开后可见:

很通俗,等于在完成 Provider 的中枢工作,提供一个创建插件类对象的 create 函数。与 SimpleWarriorProvider 近似,另外两个 Warrior 派生类 Eagle 和 Jaguar 大体亦然这样写的。暗意图如下:

在商量 Pluma 所给示例时,我已事前将 Pluma 封装成静态库了,目下要把 Eagle 和 Jaguar 编译并封装成一个动态库,就需要相连 Pluma 静态库,除此除外,还需要编译其他一些接济文献,列举如下:

豁然开朗,原来是红龙们的圣所——红玉新生圣地。

1)Connector.cpp

2)dllmain.cpp

3)Eagle.hpp

4)Jaguar.hpp

5)Warrior.cpp

其中 Connector.cpp 文献,是插件动态库向外界 Host 注册我方通盘 Provider 的地点。它必须扫尾一个 connect 函数,代码截选如下:

PLUMA_CONNECTORboolconnect(pluma::Host& host){ host.add( newEagleProvider ); host.add( newJaguarProvider ); returntrue; }

咱们先不要暴躁分析上头的 connect 看成,不错先随着我望望插件的加载经过,后文咱们就会走漏,connect 仅仅加载经过的一环费力。

4. 插件加载经过

咱们看一下 Pluma 架构所给例子的 main 函数,就不错了解插件的加载经过了:

std:: vector<WarriorProvider*> providers; pluma.getProviders(providers);

std:: vector<WarriorProvider*>::iterator it; for(it = providers.begin; it != providers.end; ++it) { Warrior* warrior = (*it)->create;std:: cout<< warrior->getDeion << std:: endl; deletewarrior; }pluma.unloadAll;std:: cout<< "Press any key to exit"; std:: cin.ignore( 10000, '\n'); return0; }

其中庸加载插件研讨的句子主要等于 pluma.acceptProviderType 和 pluma.load 两句了。前者主要认真在 Host 的 knownTypes映射表中添加一个 ProviderInfo 节点,后者认真加载插件动态库,并将动态库里匹配的 Provider 指针记入 ProviderInfo 节点。

4.1 pluma.acceptProviderType<>

咱们先说 pluma.acceptProviderType 一句。在前文先容 Pluma.inl 文献的内容时,咱们依然看到一个叫作 acceptProviderType 的模板函数了,其时莫得细说,目下我把它的代码再贴一下:

【pluma-1.1/include/pluma/Pluma.inl】

里面调用的是 PluginManager 基类的 registerType 函数。咱们前文主要体恤的是 PLUMA_PROVIDER_TYPE,目下再说一下后两个参数。PLUMA_INTERFACE_VERSION 露出搞定器现时应该使用的插件接口的版块,因为咱们不成详情更高版块的插件接口会不会加多或删除成员函数,是以这个值其实是个甘休值,若是后续用户尝试加载更高版块的插件,那么是无法通过校验的。第三个参数 PLUMA_INTERFACE_LOWEST_VERSION 则是甘休最低值,若是尝试加载比这个值更低版块的插件,笃信亦然不通晓过的。

在刚刚看到的 main 函数里,是这样写的:

也等于说,Pluma 插件搞定器对 Warrior 接口对应的 WarriorProvider 类感好奇羡慕好奇羡慕。而当初界说 Warrior 时,在 Warrior.cpp 文献里的确指明了 WarriorProvider 能甘休确现时版块号和最低版块号:

这些类型信息、版块号甘休信息都会被注册在 Host 的 knownTypes 映射表中,每种接口类型对应一个 ProviderInfo 节点。注册看成的代码如下:

【pluma-1.1/src/pluma/PluginManager.cpp】

【pluma-1.1/src/pluma/Host.cpp】

诚然,新加的 ProviderInfo 节点的 providers 列表是个空列表,待后续再添加 Provider * 内容。

4.2 pluma.load

接着,咱们连续看 main 函数里调用的 pluma.load ,其实调用的是其父类 PluginManager 的 load 。研讨代码截选如下:

【pluma-1.1/src/pluma/PluginManager.cpp】

if(host.confirmAddictions) libraries[plugName] = lib;else{ ......returnfalse; }returntrue; }

不错看到,一开动就在入辖下手加载动态库,并调用动态库里的 connect 函数。前文咱们实质上依然列举过示例代码里的 connect 函数了,目下再贴一次:

前文在进展到 connect 时,暂时莫得细说 add 看成,目下咱们来望望它的代码:

【pluma-1.1/src/pluma/Host.cpp】

// 临时放进 addRequests表addRequests[ provider->plumaGetType ].push_back(provider);returntrue; }

上头代码中阿谁 plumaGetType 函数其实是 Provider 的独到成员,一般人窥察不了,但 Host 是它的友元类,是以不错窥察。代码中会先校验待添加的 Provider 是否及格,若是及格则以 plumaGetType 复返值为 key 值,并向临时映射表 addRequests 中添加该 Provider 指针。所谓及格是指,这个 Provider 的类型是 Host 感好奇羡慕好奇羡慕的,况且其版块号亦然合适的。

值得看重的是,待添加的 Provider*,仅仅临时先放进一个 addRequests 映射表中。addRequests 映射表的界说如下:

【pluma-1.1/include/pluma/Host.hpp】

那么这个临时性的 addRequests 映射表的内容会何如处理呢?提及来也通俗,会被 “搬移” 进 Host 的 knownTypes 映射表中某个 ProviderInfo 的里面列表去。main 在调用完 connect 函数后,调用的 confirmAddictions 等于做这个事情的:

【pluma-1.1/src/pluma/Host.cpp】

咱们画一张调用干系图望望:

咱们不错通过这张调用干系图总结一下,主要经过等于在加载插件动态库,并现实动态库里的 connect 函数。该函数会将动态库里可用的通盘 Provider * 记入 Host 的 knownTypes 映射表中。同期,动态库对应的 DLibrary 对象,也会插入 Pluma 搞定类里面的 libraries 映射表中。

为了沉稳常识,咱们把前文的两张图再整合一下。

5. 使用插件 Provider5.1 pluma.getProviders

在 Providers 都添加进 Pluma 搞定类后,咱们就不错在需要时取得 provider 了,为此 Pluma 类提供了 getProviders 函数:

【pluma-1.1/src/pluma/PluginManager.cpp】

【pluma-1.1/src/pluma/Host.cpp】

代码很通俗,等于帮使用者把感好奇羡慕好奇羡慕的某类插件 Provider 通盘找出来。若是当初咱们依然通过 acceptProviderType 注册了对应的类型(PLUMA_PROVIDER_TYPE),那么至少不错拿到一个 list,不然就只可拿到 NULL 了。若是咱们不错拿到多少 Provider,就不错调用其 create 函数创建对应的插件对象了。

当工作做完后,用户应该实时 delete 掉之前创建出的插件对象。在设施退出之前,用户应该调用 pluma.unloadAll 删除通盘插件 Provider 及 DLibrary 对象。DLibrary 对象析构时,会自动关闭依然掀开的动态相连库。

【pluma-1.1/src/pluma/PluginManager.cpp】

6. 扫尾

至此,Pluma 架构的主体代码就分析罢了了,但愿对民众有所匡助。

END

这里有最新开源资讯、软件更新、技艺干货等内容

点这里 ↓↓↓ 铭记 关注✔ 标星⭐ 哦~米乐m6平台官方版

发布于:广东省声明:该文见识仅代表作家本身,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。

米乐m6下载链接 货架层板成型机

Alternate Text

米乐m6下载链接 货架层板成型机

YX40-200货架层板(承板)成型机是用于生产货架系列组件之一的货架层板开拓。坐蓐的制品为“货架层板”。多诈欺于仓储仓库、物流运输等重型货架组件之一的“货架层板”。 部件展示 『进

查看更多

米乐m6下载链接 富士康破除产线!iPhone 14或将成史上销量最差机型:苹果清库存战术失败

Alternate Text

米乐m6下载链接 富士康破除产线!iPhone 14或将成史上销量最差机型:苹果清库存战术失败

莫得任何转变和变化的iPhone 14,终究如故败了。苹果清库存权术告破。 笼统多方音讯,受iPhone 14销量不足预期影响,郑州富士康破除iPhone 14部分产线。日前,富士康里面人士观点,有部分iPh

查看更多

米乐m6平台官方版 数据中心要“下海”!公共首例商用在这儿……

Alternate Text

米乐m6平台官方版 数据中心要“下海”!公共首例商用在这儿……

◎ 采写丨科技日报记者 房琳琳 ◎ 策动丨房琳琳 何屹 本年11月下旬到12月,公共首台商用海底数据中心数据舱和配套装备,将当作海南省自贸港数字化成立的“新基建”变调示范工程,完成入

查看更多

米乐m6下载链接 摩托罗拉两款新机开售 最高不到5000元 2亿像素加持

Alternate Text

米乐m6下载链接 摩托罗拉两款新机开售 最高不到5000元 2亿像素加持

查看更多
服务热线
官方网站:www.suffolk-construction.com
工作时间:周一至周六(09:00-18:00)
联系我们
QQ:232016855
邮箱:3da28e@qq.com
地址:北京联系我们国际企业中心2264号
关注公众号

Powered by m6米乐在线客服(中国)有限公司 RSS地图 HTML地图


m6米乐在线客服(中国)有限公司-米乐m6平台官方版 聊聊Pluma插件搞定框架

回到顶部