轉自:http://hi.baidu.com/kalingna/item/e842475b9fa05b05e6c4a591
靜態連結庫、動態連結程式庫、MFC的聯絡與區別
靜態連結庫(lib)與動態連結程式庫(dll)的比較:
首先,靜態連結庫與動態連結程式庫都是共用代碼的方式,也可稱為程式模組化的方式;
靜態連結庫:
lib中的指令都被直接包含在最終的EXE中,因此exe運行時不再需要lib檔案;
不能再包含其他的動態連結程式庫或者靜態庫;
動態連結程式庫:
dll與EXE檔案獨立存在,所以發布EXE時需要同時發布dll檔案;
可以再包含其他的動態連結程式庫或者靜態庫;
建議:
請最好使用動態連結程式庫(dll)進行程式的模組化,靜態連結庫(lib)過時了(應用程式升級上就能看出其劣勢);
常用DLL查看工具 :
Dumpbin命令 或 VC++ 內建的Depends工具,可以查看某個[dll檔的匯出資訊]或某個[exe調用的dll資訊]。
DLL注意事項:
對於DLL的產生:
請謹慎使用exetern “C”;//這種方式可讀性雖高,但不支援重載等;【優劣並存】
請不要使用模組定義(.def) 檔案;//因為這種方式不夠靈活;【目前def過時了】
不要忘了使用__declspec(dllexport) 與 __declspec(dllimport);
對於編譯、運行:
請拷貝dll檔案,.lib檔案,.h檔案到exe主目錄(只要保證編譯時間exe能看到dll相關
的資訊即可);【通常做法是組織好原始碼的層次並設定好project->setting】
對於發布:
dll檔案需與exe檔案一起發布。
顯示(動態)調用方式與隱式(靜態)調用方式的比較:
顯示(動態)調用方式的特點是完全由編程者用 API 函數載入和卸載 DLL,程式員可以決定 DLL 檔案何時載入或不載入,調用方式靈活。
隱式(靜態)方式的特點是由編譯系統完成對DLL的載入和應用程式結束時 DLL 的卸載。靜態調用方式簡單易用,但不如動態調用方式靈活。
建議:
所謂的顯、隱就是針對LoadLibrary (“.dll”)而言的;
請最好使用隱式(靜態)方式,因為dll匯出介面沒用extern “C” 修飾的情況下,顯示
(動態)調用可讀性極差;而不論是否使用過extern “C”,隱式調用的介面名都與dll介面定義相同。
靜態連結庫、動態連結程式庫、MFC的聯絡與區別:
使用靜態連結庫 還是 動態連結程式庫 是一回事,用不用MFC又是另一回事!換句話說就是lib和dll都能使用MFC。
三類動態連結程式庫的比較:
Non-MFC:
不採用MFC類庫編寫,而是採用標準C風格,匯出的dll介面與標準C函數類似;
可被MFC或非MFC程式調用;
總結:(一般規則是:當程式不涉及MFC時建立該類型的dll)
Regular-MFC:
與下面的Extension-MFC類似,採用MFC類庫編寫,最明顯的特點就是包含有一個
CwinApp的派生;
在匯出的dll介面中可以使用MFC的類庫,但介面本身不能是MFC類或其衍生類別;
它又可分為靜態連結到MFC的規則dll(using MFC in static library)與動態連結(共用)到
MFC的規則dll(using MFC in shared dll);
可被任何支援DLL的語言調用(前提是要採用_stdcall約定);【我不想關心呼叫慣例】
總結:(好處是可以在dll介面中使用MFC類庫)【可使用但不可匯出MFC】
Extension-MFC:
採用MFC類庫編寫;
不僅dll介面中可以使用MFC的類庫,匯出的介面本身也可以是MFC類或其衍生類別,常用其來增強MFC的現有功能;
只能被MFC程式調用;
總結:(好處是可以用來增強MFC類庫的現有功能)
兩種規則DLL(Regular-MFC DLL)的比較:
靜態連結到MFC的規則dll(using MFC in static library):
DLL介面中預設就使用DLL自己的資源,因此不需要進行模組的資源控制代碼切換;
使用這種方法產生的規則DLL較大,因為代碼可能會重複包含;
總結:(好處是不需模組的資源控制代碼切換,但dll通常較大)
動態連結(共用)到MFC的規則dll(using MFC in shared dll):
DLL介面中預設使用的是exe的資源,所以,在DLL 介面中為了使用DLL它自己的資源或是為瞭解決資源重複問題(當DLL和主應用程式中存在相同ID的資源時),必須進行模組的資源控制代碼切換。
總結:(好處是dll通常較小,但必須進行模組的資源控制代碼切換)
動態連結(共用)到MFC的規則dll(using MFC in shared dll)時進行模組資源控制代碼切換的兩種方法:
1. dll介面函數中完成資源模組的切換工作:
//dll介面函數中切換
extern CSharedDllApp theApp;
void ShowDlg(void)
{
//狀態變更
HINSTANCE save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
CDialog dlg(IDD_DLL_DIALOG);//dll資源
dlg.DoModal();
//狀態還原
AfxSetResourceHandle(save_hInstance);
//在此處再進行操作針對的將是應用程式的資源
CDialog dlg1(IDD_DLL_DIALOG);// 應用程式的資源
dlg1.DoModal();
}
在應用程式需要的地方完成切換工作:
//應用程式中切換
void CSharedDllCallDlg::OnCalldllButton()
{
//擷取EXE模組控制代碼
HINSTANCE exe_hInstance = GetModuleHandle(NULL);
//擷取DLL模組控制代碼
HINSTANCE dll_hInstance = GetModuleHandle("SharedDll.dll");
AfxSetResourceHandle(dll_hInstance); //切換狀態
ShowDlg(); //此時顯示的是DLL的對話方塊
AfxSetResourceHandle(exe_hInstance); //恢複狀態
ShowDlg(); //此時顯示的是exe的對話方塊
}
關於DllMain的說明:
對於No-Mfc的dll及 Extension-Mfc的dll,由MFC自動提供一個;
對於Regular-Mfc,沒有定義DllMain時編程環境會自動調用一個預設版本;
總結:(也不是沒有用處,在DllMain中可以作一些初始化或者是資源回收等工作)
關於lib庫檔案的說明:
->>何時用到lib庫檔案
如果程式中採用隱式(靜態)調用dll的話,編譯時間會需要lib庫檔案。
動態連結程式庫或靜態連結庫在exe最終發布時都不需要.lib,.lib只可能在編譯期用到。
->>關於將.lib檔案匯出到特定目錄:
"project"-> "settings"-> general-> output files 裡面設定;
還可以在Pre-link step和Post-build step屬性頁面裡增加命令將檔案拷貝到相應的目錄,如:
copy debug\my.lib (特定目錄)\my.lib
copy debug\my.dll (特定目錄)\my.dll
參考:http://topic.csdn.net/t/20041222/15/3667256.html
我採用的Post-build step。編輯copy命令列時要注意,它不支援/而只能用\;
另外還要保證指定的copy目錄是存在的,否則編譯會出錯,它不會給你自動建立。
->>怎樣指明lib庫檔案的位置給linker
若採用隱式調用,連結時需要指明lib的位置,有兩種方法:
1) 使用 #pragma comment(lib,"XX.lib");
2) project->setting->LINK選項卡中的Object/Library modules:填寫lib檔案的路徑;或tools->Options->Directories內設定inc和lib的路徑;
//比如dll檔案為DllClass.dll,則填寫 Release/DllClass.lib(此處僅是樣本,請注意目錄)
前者比後者好的原因是當源檔案搬遷給其他使用者時,人家不用再去設定Project->setting...
關於純資源dll:
編寫“純資源dll”:http://hi.baidu.com/pop1210/blog/item/144192b5c6d867da36d3caa5.html
編寫“純資源dll”之二:http://hi.baidu.com/pop1210/blog/item/39a76acc5b1cf10400e92830.html
呼叫慣例, Def檔案:
一些呼叫慣例對dll的影響,用Def匯出(過時)什麼的,不想搞了,否則搞複雜了都。