動態鏈接庫編程
一。引入:
爲了使多個程序員協作開發程序,負責底層功能的程序員使用動態鏈接庫實現具體功能,負責用戶界面設計的程序員在項目中引用動態鏈接庫,並調用其中的具體功能,這樣就可以使程序具有很好的模塊化結構,便於定位和調試問題。
二。擴展名解釋:
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 著