[开源世界]增强版的动态链接库接口导出框架

给你一囗甜甜゛ 提交于 2019-11-29 03:29:28
参考: 从自动导出动态链接库接口看C++的缺点
更新内容:
1.封装了gDllImportList变量,删除了DllImportAttribute.cpp文件。
2.封装了User32类的全局变量,删除了User32.cpp文件。
更新后的框架只需要一个 DllImportAttribute.h文件,导出函数的文件也只需要一个,减少了文件数量。
#pragma once


#include <Windows.h>


#include <list>
using namespace std;


/*
 * DllImportAttribute
 * 定义加载和卸载动态链接库的接口
 */

class DllImportAttribute
{
public:
	// 加载动态链接库
	virtual BOOL Init() = 0;

	// 卸载动态链接库
	virtual BOOL Uninit() = 0;
};


/*
 * DllImportList
 * 封装gDllImportList(全局)变量,避免使用cpp文件
 */

class DllImportList
{
protected:
	static DllImportList* m_pInstance;

public:
	static DllImportList* CreateInstance()
	{
		if (m_pInstance == NULL)
		{
			m_pInstance = new DllImportList();
		}
		return m_pInstance;
	}

	static void DeleteInstance()
	{
		if (m_pInstance != NULL)
		{
			delete m_pInstance;
			m_pInstance = NULL;
		}
	}

	list<DllImportAttribute*> gDllImportList;
};


DllImportList* DllImportList::m_pInstance = NULL;


// 加载所有库,用在程序初始化的地方
inline BOOL DllImportInit()
{
	BOOL bSuccess = TRUE;

	auto& list = DllImportList::CreateInstance()->gDllImportList;	

	for (auto iter = list.begin(); iter != list.end(); iter++)
	{
		bSuccess &= (*iter)->Init();
	}

	return bSuccess;
}


// 卸载所有库,用在程序退出释放资源的地方
inline BOOL DllImportUninit()
{
	BOOL bSuccess = TRUE;

	auto& list = DllImportList::CreateInstance()->gDllImportList;	

	for (auto iter = list.begin(); iter != list.end(); iter++)
	{
		bSuccess &= (*iter)->Uninit();
	}

	// 别放了删除DllImportList实例
	DllImportList::DeleteInstance();

	return bSuccess;
}


/*
 * DLLIMPORTCLASSBEGIN
 * 定义CLASS##Dll类的前半部分,主要是库加载、卸载以及封装自身实例(避免使用Cpp文件)
 * m_nOffPtr :指示变量的位置
 */

#define DLLIMPORTCLASSBEGIN(CLASS, DLLPATH)	class CLASS##Dll : public DllImportAttribute	\
{	\
protected:	\
	HMODULE  m_hModule;	\
public:	\
	CLASS##Dll() : m_hModule(NULL) {	\
		DllImportList::CreateInstance()->gDllImportList.push_back(this);	\
	}	\
	virtual BOOL Init() {	\
		m_hModule = LoadLibraryA(DLLPATH);	\
		return (m_hModule != NULL);	\
	}	\
	virtual BOOL Uninit() {	\
		BOOL bFreeSuccess = FreeLibrary(m_hModule);	\
		CLASS##Dll::DeleteInstance();	\
		return bFreeSuccess;	\
	}	\
protected:	\
	static CLASS##Dll* m_pInstance;	\
public:	\
	static CLASS##Dll* CreateInstance()	\
	{	\
		if (m_pInstance == NULL)	\
		{	\
			m_pInstance = new CLASS##Dll();	\
			memset((BYTE*)m_pInstance + offsetof(CLASS##Dll, m_nOffPtr), 0, \
					sizeof(CLASS##Dll) - offsetof(CLASS##Dll, m_nOffPtr));	\
		}	\
		return m_pInstance;	\
	}	\
	static void DeleteInstance()	\
	{	\
		if (m_pInstance != NULL)	\
		{	\
			delete m_pInstance;	\
			m_pInstance = NULL;	\
		}	\
	}	\
protected:	\
	int m_nOffPtr;	\


/*
 * FUNCTIONENTRY
 */

#define FUNCTIONENTRY(ENTRYTYPE, ENTRYPOINT)	protected:	\
	typedef ENTRYTYPE;	\
	ENTRYPOINT ENTRYPOINT##Ptr;	\
public:	\
	ENTRYPOINT ENTRYPOINT##Func()	\
	{	\
		if (ENTRYPOINT##Ptr == NULL)	\
		{	\
			ENTRYPOINT##Ptr = (ENTRYPOINT)GetProcAddress(m_hModule, #ENTRYPOINT);	\
		}	\
		return ENTRYPOINT##Ptr;	\
	}	\


/*
 * DLLIMPORTCLASSEND
 */

#define DLLIMPORTCLASSEND(CLASS) };	\
CLASS##Dll* CLASS##Dll::m_pInstance = CLASS##Dll::CreateInstance();	\


/*
 * DLLIMPORTCALL
 */

#define DLLIMPORTCALL(CLASS, ENTRYPOINT)	CLASS##Dll::CreateInstance()->ENTRYPOINT##Func()
#pragma once


#include "DllImportAttribute.h"


DLLIMPORTCLASSBEGIN(User32, "User32.dll")
	FUNCTIONENTRY(int(WINAPI *MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT), MessageBoxA)
DLLIMPORTCLASSEND(User32)
DllImportInit();

DLLIMPORTCALL(User32, MessageBoxA)(NULL, "ad", "ad", MB_OK);

DllImportUninit();

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!