动态加载动态库DLL的通用C++模板类

在规模稍大一些的应用程序开发过程中,通常会将一部分逻辑相对独立的代码封装成类库,或者引用功能相似的外部共享类库,与主程序共同链接生成最终的应用程序。

但是为了方便将不同模块委托给独立的开发团队,并且保证主程序的开发过程不依赖具体的子模块,通常将子模块定义成具有清晰接口的实现体,并以动态库DLL形式封装。这种形态在设计模式上可以参考门面模式(Facade Pattern),也可称为外观模式。模式结构图如下所示:

关于门面模式的知识可以参考下面这位大神的文章,此处不再赘述。

23种设计模式-门面模式(外观模式)_老杨叔叔csdn的博客-CSDN博客_门面模式

以下将介绍在实际工程中提炼出的一个动态加载子系统模块的通用C++模板类,供小伙伴们参考。

//
// Filename: SubSysLoader.hpp
//

#ifndef _SUB_SYSTEM_LOADER_H_
#define _SUB_SYSTEM_LOADER_H_

#include <iostream>
#include <windows.h>

template< typename SS >
class SubSysLoader {
public:
	SubSysLoader() : _modPath(""), _creator(0), _release(0) {};

	SubSysLoader(const std::string& modPath) : 
        _modPath(modPath), _creator(0), _release(0) {
        loadModel(modPath);
	};

	virtual ~SubSysLoader() {
		if (_hModel != NULL) {
			_hModel = NULL;
			_creator = nullptr;
			_release= nullptr;
			return;
		}
	};

	//构造 方法
	SS * create() {
		if (! _creator) {
			return nullptr;
		}
		typedef  SS * (*_FUNC) ();
		return ((_FUNC)_creator)();
	};
	
	//释放 方法
	void release(SS * mod) {
		if (!_release) {
			return;
		}
		typedef  void(*_FUNC) (SS *);
		return ((_FUNC)_release)(mod);
	};

	inline bool  isValid() { return (_hModel && _creator && _release); };

private:
    bool loadModel(const std::string& modPath) {
		//动态加载DLL
		_hModel = LoadLibrary(modPath.c_str());
		if ( ! _hModel ) return false;

		//获取 DLL 中函数入口
		_creator  = GetProcAddress(_hModel, "creator");
		_release = GetProcAddress(_hModel, "release");
        return isValid();
    };

private:
	std::string _modPath;
	HINSTANCE   _hModel; //动态库句柄
	FARPROC  	_creator;
	FARPROC  	_release;
};	//[EOF SubSysLoader ]

#endif // _SUB_SYSTEM_LOADER_H_
以下详细说明一下这个通用模板类中的几个关键点:

1. 动态加载动态库的方法:

 _hModel = LoadLibrary(modPath.c_str());
 if ( ! _hModel ) return false;

以上windows系统上的实现。如果要在linux上运行,可使用 dlopen 方法。

2. 加载动态库中的 构建方法和释放方法:

 _creator = GetProcAddress(_hModel, "creator");
 _release = GetProcAddress(_hModel, "release");

此处两行代码通过 GetProcAddress 函数从动态库模块中获取 creator 和 release 两个API的入口地址。

3. 包装构建方法和释放方法:

 SS * create() //构造
 void release(SS * mod) //释放

这两个方法在成功加载动态库之后,利用动态库中的API显式创建模板对象 和 显示析构模板对象。

这里一定要强调一下:为什么动态模块中要提供 release方法,而不是直接在宿主应用中直接用 delete 方法?

理由是子系统模块中在析构对象的时候有可能需要做特殊处理,而这样的特殊处理逻辑在宿主应用中不具备的。特别是当模板类是抽象接口的时候,宿主应用中根本不知道 delete 应该使用哪个析构函数。

4. 使用方法:

有了这个通用C++模板类之后,动态加载子模块,创建子系统对象,销毁该对象就变得容易多了。参考下面的代码:

class SUBSYS_INTF_A;

SubSysLoader<SUBSYS_INTF_A> sslA(std::string(".\\plugin\\modA.dll"));
SUBSYS_INTF_A  insA = sslA.create();  //创建对象
......
sslA.release(insA);  //释放对象

以上就是本篇的全部内容,希望能帮上小伙伴们。

喜欢的话, 请点个“赞” 吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值