动态加载dll代码

本文介绍了如何动态加载名为add.dll的库,并展示了在C++中实现动态加载库的代码示例。通过设置DLL搜索路径,使用LoadLibraryExA函数加载动态库,并使用GetProcAddress获取库中的函数指针。最后,展示了如何调用动态库中的ADD和PLUS接口,以及在使用完毕后释放资源的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假如动态库add.dll接口如下:
BOOL ADD();
void PLUS();


则动态加载动态库代码.h文件如下:

#pragma once
#include <Windows.h>
#ifdef __cplusplus
extern "C"{
#endif

	typedef BOOL(*pf_ADD)();
	typedef void (*pf_PLUS)();


	class CompareSdk
	{
	public:
		CompareSdk();
		~CompareSdk();
		CompareSdk(const CompareSdk &sdk) = delete;
		CompareSdk& operator=(const CompareSdk &sdk) = delete;

		bool Init();
		void UnInit();


		static CompareSdk* Instance(){ return m_Instance; }

	public:
		// 对应的接口 
		pf_ADD m_pf_ADD = nullptr;
		pf_PLUS m_pf_PLUS = nullptr;
	

	private:
		HMODULE m_hdll;

		// 自动删除
		class AutoDel
		{
		public:
			AutoDel(){}
			~AutoDel()
			{
				if (m_Instance != nullptr)
				{
					delete m_Instance;
					m_Instance = nullptr;
				}
			}
		};

		static AutoDel m_autoDel;
	private:
		static CompareSdk* m_Instance;
	};

#ifdef __cplusplus
}
#endif


/.cpp实现如下:

#include <string>
#include "CompareSDK.h"
CompareSdk* CompareSdk::m_Instance = new CompareSdk();


CompareSdk::CompareSdk()
{

}

CompareSdk::~CompareSdk()
{

}

bool CompareSdk::Init()
{
	// 取得动态库路径
	//HMODULE module = GetModuleHandleA("add.dll");
	char buf[MAX_PATH + 1] = { 0 };
	GetModuleFileNameA(/*module*/NULL, buf, MAX_PATH);

	std::string str(buf);
	std::string::size_type pos = str.find_last_of("\\");
	std::string dllpath = str;
	if (pos != std::string::npos)
	{
		dllpath = str.substr(0, pos);
	}
	dllpath += "\\cmpSdk\\add.dll";

	// 设置当前动态库路径后再加载动态库
	bool bsucc = SetDllDirectoryA(dllpath.c_str());
	m_hdll = LoadLibraryExA(dllpath.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);//LOAD_WITH_ALTERED_SEARCH_PATH,让系统DLL搜索顺序从DLL所在目录开始
	DWORD ret = GetLastError();
	printf("LoadLibraryA path[%s] %s, err[%d]", dllpath.c_str(), m_hdll == NULL ? "fail" : "succ",ret);
	if (m_hdll == nullptr)
	{
		return false;
	}

	// 加载对应接口
	m_pf_ADD = (pf_ADD)GetProcAddress(m_hdll, "ADD");
	m_pf_PLUS = (pf_PLUS)GetProcAddress(m_hdll, "PLUS");


	if(m_pf_ADD == nullptr ||
	   m_pf_PLUS == nullptr)
	{
		return false;
	}

	return true;
}

void CompareSdk::UnInit()
{
	if (m_hdll != nullptr)
	{
		FreeLibrary(m_hdll);
		m_hdll = nullptr;
	}
}


// 调用
CompareSdk::Instance()->Init(); // 加载动态库

// 调用动态库函数
CompareSdk::Instance()->m_pf_ADD();
CompareSdk::Instance()-m_pf_PLUS();

//使用完后释放资源
CompareSdk::Instance()->UnInit();


                
程序中加载了一个DLL文件,但生成的EXE在脱离了DLL文件后仍然可以 单独使用,这是动态加载DLL技术。即:调用资源中的DLL。 此技术的好处:EXE可以使用DLL中的函数,但不会额外增加一 个DLL文件,在使用DLL文件的时候不需要先把DLL释放到硬盘。 在动态加载的这个DLL中定义了一个函数MRun,该函数可以动态执行一 个EXE,即:调用资源中的EXE文件或TMemoryStream中被载入的EXE流。 此技术的好处:直接把资源中的EXE加载到内存中执行,使用程序自 身嵌入的EXE文件的时候不需要先把EXE释放到硬盘上就可以直接执行。 对保密EXE文件很有用。例如:我编写的程序是A.exe,它在运行后需要 使用B.exe,而B.exe是别人编写的我没有源码,但我必须又要在我的程 序中用B.exe,这时我就把它包含到我的A.exe中,这个非常容易做到, 但是,程序A.exe在使用程序B.exe的时候按照常理必须先把B.exe释放 到硬盘上才可以用WinExec或ShellExecute等函数调用它,但你在释放 到硬盘上的时候容易被别人直接复制走,而你只想让别人用你的A.exe不 想让别人直接用B.exe(因为B.exe是别人写的等原因),此时如何保密 B.exe呢?这时只要用到上面所说的MRun函数就可以了,程序A.exe在执 行B.exe的时候不需要释放到硬盘上就可以直接执行B.exe啦,是不是很爽? 说一下MRun的调用方式: MRun(流,参数,进程id); 调用成功返回True,失败返回False,三个参数解释如下: 第一个参数:一个载入了EXE的资源流或者内存流等流类型。 第二个参数:传递调用EXE的参数。如果EXE调用不需要参数,可设置为空串。 第三个参数:如果调用成功,则返回被调用的EXE对应的进程ID。 细节性问题,请直接双击Project1.dpr文件进入演示代码,了解更多。演示代 码中动态加载了MemRun.dll文件,动态调用了5555044.exe文件,如果你想更换 动态调用的EXE文件,只需要用其它EXE覆盖5555044.exe文件并双击Clear.bat 文件后,在Delphi中按F9重新编译运行即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值