动态链接库编程
一。引入:
为了使多个程序员协作开发程序,负责底层功能的程序员使用动态链接库实现具体功能,负责用户界面设计的程序员在项目中引用动态链接库,并调用其中的具体功能,这样就可以使程序具有很好的模块化结构,便于定位和调试问题。
二。扩展名解释:
dll – Dynamic-link library – 动态链接库
1. dll –- 共享库
2.ocx –- 包含Active控件的动态链接库
3.drv --- 系统驱动程序
三。相关知识概括(如下图):
四。代码示例
// dllmain.cpp : 定义 DLL 应用程序的入口点。
//生成项目,可以得到一个.dll文件和一个.lib文件.
#include <windows.h>
// DLLMain是DLL的入口函数
BOOL APIENTRY DllMain( HMODULE hModule, // DLL的句柄
DWORD ul_reason_for_call, // 指定调用DLL入口函数的原因
LPVOID lpReserved // 指定DLL初始化和清理的方式
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: // DLL正在加载到当前进程时虚拟地址空间
case DLL_THREAD_ATTACH: // 进程正在创建一个线程,并在线程中加载DLL
case DLL_THREAD_DETACH: // 表示调用DLL的线程正在清理和退出
case DLL_PROCESS_DETACH:// 表示在进程退出过程中或调用FreeLibrary()函数时,DLL正在从当前进程的虚拟地址空间卸载
break;
}
return TRUE;
}
// 添加导出函数
extern "C"_declspec(dllexport) int sum (int a, int b)
{
return a + b;
}
// 添加导出类
class _declspec(dllexport) CMath
{
public:
CMath(void);
int sum(int , int);
~CMath(void);
};
CMath::CMath(void)
{
}
int CMath::sum(int a, int b)
{
return a + b;
}
CMath::~CMath(void)
{
}
// HideReferenceDLL.cpp -- 隐式链接使用DLL
#include <iostream>
#include <Windows.h>
// 隐式链接:加载动态链接库
#pragma comment(lib, "win32.lib")
// 导出声明不能在函数里面使用,链接时应该在函数的外部使用(全局作用域)
extern "C" int sum(int a, int b);
extern "C" class _declspec(dllexport)CMath
{
public:
CMath(void);
int sum(int , int);
~CMath(void);
};
int main()
{
std::cout << "5 + 6 = " << sum(5, 6) << std::endl
<< "成功引用DLL中的导出函数\n";
CMath testClass;
std::cout << "7 + 8 = " << testClass.sum(7, 8) << std::endl
<< "成功引用DLL中的导出类\n";
system("pause");
return 0;
}
// obviousReferenceDLL.cpp -- 显式链接
#include <stdio.h>
#include <Windows.h>
int main()
{
// 申请变量
HINSTANCE hinstLib; // 指定DLL模块的句柄
typedef int (*PROCSUM)(int, int);
PROCSUM procSum; // 指定DLL模块中导出模块的地址
// 加载DLL文件,获取DLL句柄
hinstLib = LoadLibrary(TEXT("win32.dll"));
// 如果句柄有效,则获取函数sum()的地址
if(NULL != hinstLib){
wprintf(L"LoadLibrary() is OK!\n");
procSum = (PROCSUM) GetProcAddress(hinstLib, "sum"); // 获取dll导出函数的地址
// If the function address is valid, call the functuon.
if(procSum != NULL){
printf("GetProcAddress() is OK!\n");
printf("5+6 = %d\n", (procSum)(5, 6));
}
else{
printf("LoadLibrary() failed, error %d\n", GetLastError());
FreeLibrary(hinstLib);
}
}
else{
printf("LoadLibrary() failed, error %d \n", GetLastError());
}
system("pause");
return 0;
}
五。学习参考资料
1. MSDN Library for Visual Studio 2005
2. 《Windows系统编程》 李晓黎 编著
3. 《Windows系统编程》 Johnson M.Hart 著