1.2.3 靜態(tài)庫(kù)優(yōu)缺點(diǎn)
- 靜態(tài)庫(kù)對(duì)函數(shù)庫(kù)的鏈接是放在編譯時(shí)期完成的,靜態(tài)庫(kù)在程序的鏈接階段被復(fù)制到了程序中,和程序運(yùn)行的時(shí)候沒(méi)有關(guān)系;
- 程序在運(yùn)行時(shí)與函數(shù)庫(kù)再無(wú)瓜葛,移植方便。
- 浪費(fèi)空間和資源,所有相關(guān)的目標(biāo)文件與牽涉到的函數(shù)庫(kù)被鏈接合成一個(gè)可執(zhí)行文件。
|
內(nèi)存和磁盤(pán)空間
靜態(tài)鏈接這種方法很簡(jiǎn)單,原理上也很容易理解,在操作系統(tǒng)和硬件不發(fā)達(dá)的早期,絕大部門(mén)系統(tǒng)采用這種方案。隨著計(jì)算機(jī)軟件的發(fā)展,這種方法的缺點(diǎn)很快暴露出來(lái),那就是靜態(tài)鏈接的方式對(duì)于計(jì)算機(jī)內(nèi)存和磁盤(pán)空間浪費(fèi)非常嚴(yán)重。特別是多進(jìn)程操作系統(tǒng)下,靜態(tài)鏈接極大的浪費(fèi)了內(nèi)存空間。在現(xiàn)在的linux系統(tǒng)中,一個(gè)普通程序會(huì)用到c語(yǔ)言靜態(tài)庫(kù)至少在1MB以上,那么如果磁盤(pán)中有2000個(gè)這樣的程序,就要浪費(fèi)將近2GB的磁盤(pán)空間。
程序開(kāi)發(fā)和發(fā)布
空間浪費(fèi)是靜態(tài)鏈接的一個(gè)問(wèn)題,另一個(gè)問(wèn)題是靜態(tài)鏈接對(duì)程序的更新、部署和發(fā)布也會(huì)帶來(lái)很多麻煩。比如程序中所使用的mylib.lib是由一個(gè)第三方廠商提供的,當(dāng)該廠商更新容量mylib.lib的時(shí)候,那么我們的程序就要拿到最新版的mylib.lib,然后將其重新編譯鏈接后,將新的程序整個(gè)發(fā)布給用戶(hù)。這樣的做缺點(diǎn)很明顯,即一旦程序中有任何模塊更新,整個(gè)程序就要重新編譯鏈接、發(fā)布給用戶(hù),用戶(hù)要重新安裝整個(gè)程序。
1.3 vs下動(dòng)態(tài)庫(kù)創(chuàng)建和使用
要解決空間浪費(fèi)和更新困難這兩個(gè)問(wèn)題,最簡(jiǎn)單的辦法就是把程序的模塊相互分割開(kāi)來(lái),形成獨(dú)立的文件,而不是將他們靜態(tài)的鏈接在一起。簡(jiǎn)單地講,就是不對(duì)哪些組成程序的目標(biāo)程序進(jìn)行鏈接,等程序運(yùn)行的時(shí)候才進(jìn)行鏈接。也就是說(shuō),把整個(gè)鏈接過(guò)程推遲到了運(yùn)行時(shí)再進(jìn)行,這就是動(dòng)態(tài)鏈接的基本思想。
1.3.1 動(dòng)態(tài)庫(kù)的創(chuàng)建
1. 創(chuàng)建一個(gè)新項(xiàng)目,在已安裝的模板中選擇“常規(guī)”,在右邊的類(lèi)型下選擇“空項(xiàng)目”,在名稱(chēng)和解決方案名稱(chēng)中輸入mydll。點(diǎn)擊確定。
2.在解決方案資源管理器的頭文件中添加,mydll.h文件,在源文件添加mydll.c文件(即實(shí)現(xiàn)文件)。
3.在test.h文件中添加如下代碼:
#ifndef TEST_H
#define TEST_H
__declspec(dllexport) int myminus(int a, int b);
#endif |
- 在test.c文件中添加如下代碼:
#include"test.h"
__declspec(dllexport) int myminus(int a, int b){
return a - b;
} |
5. 配置項(xiàng)目屬性。因?yàn)檫@是一個(gè)動(dòng)態(tài)鏈接庫(kù),所以應(yīng)在項(xiàng)目屬性的“配置屬性”下選擇“常規(guī)”,在其下的配置類(lèi)型中選擇“動(dòng)態(tài)庫(kù)(.dll)。
6.編譯生成新的解決方案,在Debug文件夾下會(huì)得到mydll.dll (對(duì)象文件庫(kù)),將該.dll文件、.lib文件和相應(yīng)頭文件給用戶(hù),用戶(hù)就可以使用該庫(kù)里的函數(shù)了。
疑問(wèn)一:__declspec(dllexport)是什么意思?
動(dòng)態(tài)鏈接庫(kù)中定義有兩種函數(shù):導(dǎo)出函數(shù)(export function)和內(nèi)部函數(shù)(internal function)。 導(dǎo)出函數(shù)可以被其它模塊調(diào)用,內(nèi)部函數(shù)在定義它們的DLL程序內(nèi)部使用。
疑問(wèn)二:動(dòng)態(tài)庫(kù)的lib文件和靜態(tài)庫(kù)的lib文件的區(qū)別?
在使用動(dòng)態(tài)庫(kù)的時(shí)候,往往提供兩個(gè)文件:一個(gè)引入庫(kù)(.lib)文件(也稱(chēng)“導(dǎo)入庫(kù)文件”)和一個(gè)DLL(.dll)文件。雖然引入庫(kù)的后綴名也是“lib”,但是,動(dòng)態(tài)庫(kù)的引入庫(kù)文件和靜態(tài)庫(kù)文件有著本質(zhì)的區(qū)別,對(duì)一個(gè)DLL文件來(lái)說(shuō),其引入庫(kù)文件(.lib)包含該DLL導(dǎo)出的函數(shù)和變量的符號(hào)名,而.dll文件包含該DLL實(shí)際的函數(shù)和數(shù)據(jù)。在使用動(dòng)態(tài)庫(kù)的情況下,在編譯鏈接可執(zhí)行文件時(shí),只需要鏈接該DLL的引入庫(kù)文件,該DLL中的函數(shù)代碼和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件,直到可執(zhí)行程序運(yùn)行時(shí),才去加載所需的DLL,將該DLL映射到進(jìn)程的地址空間中,然后訪問(wèn)DLL中導(dǎo)出的函數(shù)。 |
1.3.2 動(dòng)態(tài)庫(kù)的使用
方法一:隱式調(diào)用
創(chuàng)建主程序TestDll,將mydll.h、mydll.dll和mydll.lib復(fù)制到源代碼目錄下。
(P.S:頭文件Func.h并不是必需的,只是C++中使用外部函數(shù)時(shí),需要先進(jìn)行聲明)
在程序中指定鏈接引用鏈接庫(kù) : #pragma comment(lib,"./mydll.lib") |
方法二:顯式調(diào)用
HANDLE hDll; //聲明一個(gè)dll實(shí)例文件句柄
hDll = LoadLibrary("mydll.dll"); //導(dǎo)入動(dòng)態(tài)鏈接庫(kù)
MYFUNC minus_test; //創(chuàng)建函數(shù)指針
//獲取導(dǎo)入函數(shù)的函數(shù)指針
minus_test = (MYFUNC)GetProcAddress(hDll, "myminus"); |
本文版權(quán)歸傳智播客C++培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:傳智播客C/C++培訓(xùn)學(xué)院
首發(fā):http://m.8y3kgpwe.cn/c/