动态链接库DLL的动态加载
DLL,即动态链接库(Dynamic Link Library),在实际应用开发过程中,为了以后对已经开发好的软件程序进行更好的维护和管理,程序的模块化是一个很好的管理方法,程序员大都喜欢把某一模块的功能做成dll文件,然后导入到工程目录中,再进行加载即可调用dll里面的函数,大大的减少了代码的阅读量,节省大量的宝贵时间,如果需要对dll里面的具体方法进行修改,直接打开生成dll文件即可,不需要在整个工程项目中查找,如果工程量较大,那查找其中某一个模块必定是一件费时的事情。那也说明了dll/模块化细想的重要性。
动态链接库的加载方式:
一.动态加载 (显式调用)
二.静态加载(隐式调用)
静态链接库:
1.lib中的函数不仅被连接,而且全部实现都被直接包含在最终生成的EXE文件中,但是其具体实现是不可见的。
2.静态调用中,由编译系统完成对DLL的加载和应用程序结束时DLL的卸载:
释放已经加载的DLL模块: FreeLibrary(hDll);
3.静态调用:.cpp文件中包含对应的.h文件,并写上如下语句:
#pragma comment(lib,"xxx.lib") //告诉编译器DLL相对应的lib文件所在路径和文件名
extern "C" _declspec(dllimport) int _stdcall Camera();//声明导入函数
动态链接库:
1.dll不必被包含在最终的EXE中,动态调用时仅把函数名或者变量名或者类名链接到.EXE文件中,而这些东西的实体都只有在运行时才从动态库中导入到可执行
文件中,动态调用中.EXE文件执行时可以直接动态地引用和卸载DLL文件。
2.动态调用中,由程序员用API函数加载和卸载DLL
方式:(DLL加载—DLL函数地址获取—DLL释放)
注意:静态链接库中不能再包含其他的动态链接库或静态库,而动态链接库中可以包含其他的动态或静态库。
导出函数的声明方式:
方式1:在函数声明类型和函数名之间加上“_declspec(dllexport)”。
方式2:采用模块定义(.def)文件声明,需要在库工程中添加模块文件,格式如下:
LIBRARY 库工程名称
EXPORTS 导出函数名
同时,DLL导出函数(或变量、类)可供应用程序调用;DLL内部函数只能在DLL程序内使用,应用程序无法调用它们。
一、创建动态链接库(MFC规则DLL)
其实,DLL的编制与具体的编程语言及编译器无关,VC++支持三种DLL:非MFC动态库、MFC规则DLL、MFC扩展DLL。
创建步骤:
1. 新建一个MFC AppWizard(dll),动态链接库使用 共享MFC DLL
2. def文件中添加:函数名(Camera)
3. h文件中添加:外部函数声明 ,如:Initialize
extern “C” __declspec(dllexport) int __stdcall Initialize();
4. cpp文件中添加: 外部函数实现
extern “C” __declspec(dllexport) int __stdcall Initialize()
{
//函数具体功能
}
或者用以下例子创建dll
.h文件:
#pragma once
class Camera
{
public:
virtual BOOL Initialize() = 0;
virtual void DeleteThis() = 0;
//xxx
//xxx
};
//定义一个与Add_new函数接受参数类型和返回值均相同的函数指针类型
typedef Camera* (__stdcall * CREATE_Camera )();
需要在.cpp文件中对其函数具体实现,这里主要是说明如何应用,如何实现就不写出来了。
对于 dll的加载,下面给出1个例子来说明:
首先,假设已经有一个Camera.dll 和Camera.ib文件,把其拷背到项目工程debug目录下,然后在调用处进行加载
根据名字/地址进行动态加载:
步骤:
1.使用LoadLibrary载入动态链接库
2.使用GetProcAddress获取函数地址
//Dll文件
CString strDllName = _T("Camera.dll");
//句柄
HINSTANCE m_hInstDLL;
//动态加载DLL模块句柄
m_hInstDLL = ::LoadLibrary (strDllName);
//函数指针
CREATE_Camera pfCreate;
if (m_hInstDLL == NULL)
{
AfxMessageBox(_T("Load library: ")+ strDllName + _T(" fail!"));
}
else
{
//1.根据地址加载:得到所加载DLL模块中函数的地址
//CREATE_Camera pfCreate = (CREATE_Camera)::GetProcAddress (m_hInstDLL, "?CreateDVPCamera@@YAPAVCCamera@@XZ");
//2.根据名字加载:
pfCreate =(CREATE_Camera)::GetProcAddress(m_hInstDLL,"CreateDVPCamera");
if( !pfCreate )
{
AfxMessageBox(_T("Load library: ") + strDllName + _T(",Fail to Get Proc address:")+_T("CreateDVPCamera"));
DWORD dErr = GetLastError();
}
else
{
m_pCamera = (*pfCreate)();
m_Camera->Initialize();
AfxMessageBox(_T("success ") );
}
}
说明:
上面例子中,根据地址加载方式中,地址
“?CreateDVPCamera@@YAPAVCCamera@@XZ”
要通过Dependency Walker工具打开DLL文件直接进行获得。