久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Qt DLL總結(jié)【一】-鏈接庫預(yù)備知識 - 柳北風(fēng)兒~~~~~~~欲宇仙炅 - ITeye技術(shù)網(wǎng)站

 海洋619 2015-01-30

目錄


Qt DLL總結(jié)【一】-鏈接庫預(yù)備知識


Qt DLL總結(jié)【二】-創(chuàng)建及調(diào)用QT的 DLL  


Qt DLL總結(jié)【三】-VS2008+Qt 使用QPluginLoader訪問DLL




1、鏈接庫概念




靜態(tài)鏈接庫和動態(tài)鏈接庫介紹    


     我們可以創(chuàng)建一種文件里面包含了很多函數(shù)和變量的目標(biāo)代碼,,鏈接的時(shí)候只要把這個(gè)文件指示給鏈接程序就自動地從文件中查找符合要求的函數(shù)和變量進(jìn)行鏈接,,整個(gè)查找過程根本不需要我們操心。


     這個(gè)文件叫做 “庫(Libary)”,,平時(shí)我們把編譯好的目標(biāo)代碼存儲到“庫”里面,,要用的時(shí)候鏈接程序幫我們從庫里面找出來。


 


靜態(tài)鏈接庫:


  在早期庫的組織形式相對簡單,,里面的目標(biāo)代碼只能夠進(jìn)行靜態(tài)鏈接,,所以我們稱為“靜態(tài)庫”,靜態(tài)庫的結(jié)構(gòu)比較簡單,,其實(shí)就是把原來的目標(biāo)代碼放在一起,,鏈接程序根據(jù)每一份目標(biāo)代碼的符號表查找相應(yīng)的符號(函數(shù)和變量的名字),找到的話就把該函數(shù)里面需要定位的進(jìn)行定位,,然后將整塊函數(shù)代碼放進(jìn)可執(zhí)行文件里,,若是找不到需要的函數(shù)就報(bào)錯(cuò)退出。


     靜態(tài)庫的兩個(gè)特點(diǎn):


      1,、鏈接后產(chǎn)生的可執(zhí)行文件包含了所有需要調(diào)用的函數(shù)的代碼,,因此占用磁盤空間較大。


      2,、如果有多個(gè)(調(diào)用相同庫函數(shù)的)進(jìn)程在內(nèi)存中同時(shí)運(yùn)行,,內(nèi)存中就存有多份相同的庫函數(shù)代碼,因此占用內(nèi)存空間較多,。




動態(tài)鏈接庫:


      動態(tài)鏈接庫就是為了解決這些問題而誕生的技術(shù),顧名思義,,動態(tài)鏈接的意思就是在程序裝載內(nèi)存的時(shí)候才真正的把庫函數(shù)代碼鏈接進(jìn)行確定它們的地址,,并且就算有幾個(gè)程序同時(shí)運(yùn)行,內(nèi)存也只存在一份函數(shù)代碼。


  動態(tài)庫的代碼必須滿足這樣一種條件:能夠被加載到不同進(jìn)程的不同地址,,所以代碼要經(jīng)過特別的編譯處理,,我們把這種經(jīng)過特別處理的代碼叫做“位置無關(guān)代碼(Position independed Code .PIC)”.


  根據(jù)載入程序何時(shí)確定動態(tài)代碼的邏輯地址,可以把動態(tài)裝載分為兩類,。




      1,、靜態(tài)綁定(static binding)


     使用靜態(tài)綁定的程序一開始載入內(nèi)存的時(shí)候,載入程序就會把程序所有調(diào)用到的動態(tài)代碼的地址算出確定下來,,這種方式使程序剛運(yùn)行的初始化時(shí)間較長,,不過旦完成動態(tài)裝載,程序的運(yùn)行速度就很快,。




      2,、動態(tài)綁定(dynamic binding)


      使用這種方式的程序并不在一開始就完成動態(tài)鏈接,而是直到真正調(diào)用動態(tài)庫代碼時(shí),,載入程序才計(jì)算(被調(diào)用的那部分)動態(tài)代碼的邏輯地址,,然后等到某個(gè)時(shí)候,程序又需要調(diào)用另外某塊動態(tài)代碼時(shí),,載入程序又去計(jì)算這部分代碼的邏輯地址,,所以,這種方式使程序初始化時(shí)間較短,,但運(yùn)行期間的性能比不上靜態(tài)綁定的程序,。




      平時(shí)默認(rèn)進(jìn)行鏈接的標(biāo)準(zhǔn) C/C++ 函數(shù)就是動態(tài)庫。




 2,、鏈接庫常識

      目前以lib后綴的庫有兩種,,一種為靜態(tài)鏈接庫(Static Libary,以下簡稱“靜態(tài)庫”),,另一種為動態(tài)連接庫(DLL,,以下簡稱“動態(tài)庫”)的導(dǎo)入庫(Import Libary,以下簡稱“導(dǎo)入庫”),。 

      靜態(tài)庫是一個(gè)或者多個(gè)obj文件的打包,,所以有人干脆把從obj文件生成lib的過程稱為Archive,即合并到一起,。比如你鏈接一個(gè)靜態(tài)庫,,如果其中有錯(cuò),它會準(zhǔn)確的找到是哪個(gè)obj有錯(cuò),,即靜態(tài)lib只是殼子,。 

      動態(tài)庫一般會有對應(yīng)的導(dǎo)入庫,方便程序靜態(tài)載入動態(tài)鏈接庫,,否則你可能就需要自己LoadLibary調(diào)入DLL文件,,然后再手工GetProcAddress獲得對應(yīng)函數(shù)了。有了導(dǎo)入庫,你只需要鏈接導(dǎo)入庫后按照頭文件函數(shù)接口的聲明調(diào)用函數(shù)就可以了,。

     導(dǎo)入庫和靜態(tài)庫的區(qū)別很大,,他們實(shí)質(zhì)是不一樣的東西。靜態(tài)庫本身就包含了實(shí)際執(zhí)行代碼,、符號表等等,,而對于導(dǎo)入庫而言,其實(shí)際的執(zhí)行代碼位于動態(tài)庫中,,導(dǎo)入庫只包含了地址符號表等,,確保程序找到對應(yīng)函數(shù)的一些基本地址信息。 這也是實(shí)際上很多開源代碼發(fā)布的慣用方式:


     1. 預(yù)編譯的開發(fā)包:包含一些.dll文件和一些.lib文件,。其中這里的.lib就是導(dǎo)入庫,,而不要錯(cuò)以為是靜態(tài)庫。但是引入方式和靜態(tài)庫一樣,,要在鏈接路徑上添加找到這些.lib的路徑,。而.dll則最好放到最后產(chǎn)生的應(yīng)用程序exe執(zhí)行文件相同的目錄。這樣運(yùn)行時(shí),,就會自動調(diào)入動態(tài)鏈接庫,。

      2. 用戶自己編譯: 下載的是源代碼,按照readme自己編譯,。生成很可能也是.dll + .lib(導(dǎo)入庫)的庫文件

      3. 如果你只有dll,,并且你知道dll中函數(shù)的函數(shù)原型,那么你可以直接在自己程序中使用LoadLibary調(diào)入DLL文件,,GetProcAddress

DLL: 

      動態(tài)鏈接庫 (DLL) 是作為共享函數(shù)庫的可執(zhí)行文件,。動態(tài)鏈接提供了一種方法,使進(jìn)程可以調(diào)用不屬于其可執(zhí)行代碼的函數(shù),。函數(shù)的可執(zhí)行代碼位于一個(gè) DLL 中,,該 DLL 包含一個(gè)或多個(gè)已被編譯、鏈接并與使用它們的進(jìn)程分開存儲的函數(shù),。DLL 還有助于共享數(shù)據(jù)和資源,。多個(gè)應(yīng)用程序可同時(shí)訪問內(nèi)存中單個(gè) DLL 副本的內(nèi)容。 

      動態(tài)鏈接與靜態(tài)鏈接的不同之處在于它允許可執(zhí)行模塊(.dll 文件或 .exe 文件)僅包含在運(yùn)行時(shí)定位 DLL 函數(shù)的可執(zhí)行代碼所需的信息,。在靜態(tài)鏈接中,,鏈接器從靜態(tài)鏈接庫獲取所有被引用的函數(shù),并將庫同代碼一起放到可執(zhí)行文件中,。 


         使用動態(tài)鏈接代替靜態(tài)鏈接有若干優(yōu)點(diǎn),。擴(kuò)展了應(yīng)用程序的特性、,、可以用許多種編程語言來編寫,、簡化了軟件項(xiàng)目的管理,、有助于節(jié)省內(nèi)存、有助于資源共享,、有助于應(yīng)用程序的本地化、有助于解決平臺差異,、可以用于一些特殊的目的,。windows使得某些特性只能為DLL所用。



3,、動態(tài)鏈接庫的調(diào)用


      有兩種類型的鏈接:隱式鏈接和顯式鏈接,。



隱式鏈接

      應(yīng)用程序的代碼調(diào)用導(dǎo)出 DLL 函數(shù)時(shí)發(fā)生隱式鏈接。 當(dāng)調(diào)用可執(zhí)行文件的源代碼被編譯或被匯編時(shí),,DLL 函數(shù)調(diào)用在對象代碼中生成一個(gè)外部函數(shù)引用,。 若要解析此外部引用,應(yīng)用程序必須與 DLL 的創(chuàng)建者所提供的導(dǎo)入庫(.LIB 文件)鏈接,。

      導(dǎo)入庫僅包含加載 DLL 的代碼和實(shí)現(xiàn) DLL 函數(shù)調(diào)用的代碼,。 在導(dǎo)入庫中找到外部函數(shù)后,會通知鏈接器此函數(shù)的代碼在 DLL 中,。 要解析對 DLL 的外部引用,,鏈接器只需向可執(zhí)行文件中添加信息,通知系統(tǒng)在進(jìn)程啟動時(shí)應(yīng)在何處查找 DLL 代碼,。

      系統(tǒng)啟動包含動態(tài)鏈接引用的程序時(shí),,它使用程序的可執(zhí)行文件中的信息定位所需的 DLL。 如果系統(tǒng)無法定位 DLL,,它將終止進(jìn)程并顯示一個(gè)對話框來報(bào)告錯(cuò)誤,。 否則,系統(tǒng)將 DLL 模塊映射到進(jìn)程的地址空間中,。

       如果任何 DLL 具有(用于初始化代碼和終止代碼的)入口點(diǎn)函數(shù),,操作系統(tǒng)將調(diào)用此函數(shù)。 在傳遞到入口點(diǎn)函數(shù)的參數(shù)中,,有一個(gè)指定用以指示 DLL 正在附帶到進(jìn)程的代碼,。 如果入口點(diǎn)函數(shù)沒有返回 TRUE,系統(tǒng)將終止進(jìn)程并報(bào)告錯(cuò)誤,。

       最后,,系統(tǒng)修改進(jìn)程的可執(zhí)行代碼以提供 DLL 函數(shù)的起始地址。

       與程序代碼的其余部分一樣,,DLL 代碼在進(jìn)程啟動時(shí)映射到進(jìn)程的地址空間中,,且僅當(dāng)需要時(shí)才加載到內(nèi)存中。 因此,,由 .def 文件用來在 Windows 的早期版本中控制加載的 PRELOAD 和 LOADONCALL 代碼特性不再具有任何意義,。



顯式鏈接

      大部分應(yīng)用程序使用隱式鏈接,,因?yàn)檫@是最易于使用的鏈接方法。 但是有時(shí)也需要顯式鏈接,。 下面是一些使用顯式鏈接的常見原因:

      直到運(yùn)行時(shí),,應(yīng)用程序才知道需要加載的 DLL 的名稱。 例如,,應(yīng)用程序可能需要從配置文件獲取 DLL 的名稱和導(dǎo)出函數(shù)名,。

      如果在進(jìn)程啟動時(shí)未找到 DLL,操作系統(tǒng)將終止使用隱式鏈接的進(jìn)程,。 同樣是在此情況下,,使用顯式鏈接的進(jìn)程則不會被終止,并可以嘗試從錯(cuò)誤中恢復(fù),。 例如,,進(jìn)程可通知用戶所發(fā)生的錯(cuò)誤,并讓用戶指定 DLL 的其他路徑,。

      如果使用隱式鏈接的進(jìn)程所鏈接到的 DLL 中有任何 DLL 具有失敗的 DllMain 函數(shù),,該進(jìn)程也會被終止。 同樣是在此情況下,,使用顯式鏈接的進(jìn)程則不會被終止,。

      因?yàn)?Windows 在應(yīng)用程序加載時(shí)加載所有的 DLL,故隱式鏈接到許多 DLL 的應(yīng)用程序啟動起來會比較慢,。 為提高啟動性能,,應(yīng)用程序可隱式鏈接到那些加載后立即需要的 DLL,并等到在需要時(shí)顯式鏈接到其他 DLL,。

      顯式鏈接下不需將應(yīng)用程序與導(dǎo)入庫鏈接,。 如果 DLL 中的更改導(dǎo)致導(dǎo)出序號更改,使用顯式鏈接的應(yīng)用程序不需重新鏈接(假設(shè)它們是用函數(shù)名而不是序號值調(diào)用 GetProcAddress),,而使用隱式鏈接的應(yīng)用程序必須重新鏈接到新的導(dǎo)入庫,。



     下面是需要注意的顯式鏈接的兩個(gè)缺點(diǎn):



     如果 DLL 具有 DllMain 入口點(diǎn)函數(shù),則操作系統(tǒng)在調(diào)用 LoadLibrary 的線程上下文中調(diào)用此函數(shù),。 如果由于以前調(diào)用了 LoadLibrary 但沒有相應(yīng)地調(diào)用 FreeLibrary 函數(shù)而導(dǎo)致 DLL 已經(jīng)附加到進(jìn)程,,則不會調(diào)用此入口點(diǎn)函數(shù)。 如果 DLL 使用 DllMain 函數(shù)為進(jìn)程的每個(gè)線程執(zhí)行初始化,,顯式鏈接會造成問題,,因?yàn)檎{(diào)用 LoadLibrary(或 AfxLoadLibrary)時(shí)存在的線程將不會初始化。

      如果 DLL 將靜態(tài)作用域數(shù)據(jù)聲明為 __declspec(thread),,則在顯式鏈接時(shí) DLL 會導(dǎo)致保護(hù)錯(cuò)誤,。 用 LoadLibrary 加載 DLL 后,每當(dāng)代碼引用此數(shù)據(jù)時(shí) DLL 就會導(dǎo)致保護(hù)錯(cuò)誤,。 (靜態(tài)作用域數(shù)據(jù)既包括全局靜態(tài)項(xiàng),,也包括局部靜態(tài)項(xiàng),。)因此,創(chuàng)建 DLL 時(shí)應(yīng)避免使用線程本地存儲區(qū),,或者應(yīng)(在用戶嘗試動態(tài)加載時(shí))告訴 DLL 用戶潛在的缺陷,。




4、顯示鏈接和隱式鏈接的區(qū)別




一,、Implicit Linking(隱式連接)

       Implicit Linking(隱式連接) ,,又叫靜態(tài)載入,所謂靜態(tài)載入是指程序在連接時(shí)期即與dlls所對應(yīng)的import libraries作靜態(tài)連接,,于是可執(zhí)行文件中便對所有的dll函數(shù)都有一份重定位表格(relocation table)和待修正記錄(fixup record)。當(dāng)程序被windows載入器載入內(nèi)存中時(shí),,載入器會自動修正所有的fixup records,,而這個(gè)fixup records 就是記錄DLL中所有輸出資源的正確位置地址,經(jīng)過這樣的程序動態(tài)連接便自動產(chǎn)生,。也就是說,,程序開始執(zhí)行時(shí),會用靜態(tài)載入的方式時(shí)所使用的DLLs都載入到程序的內(nèi)存里,。

      靜態(tài)載入方式的優(yōu)點(diǎn)

      1,、靜態(tài)載入方式所使用的dll會在應(yīng)用程序執(zhí)行時(shí)載入,然后就可以調(diào)用所有dll中提供的函數(shù),,就像是程序中一樣,。

      2、處理簡單,,載入的方法有編譯器負(fù)責(zé)處理,,不需動腦筋。

 

      靜態(tài)載入方式的缺點(diǎn)

      1,、當(dāng)程序機(jī)構(gòu)態(tài)載入方式所使用的dll不存在時(shí),,程序開始就會報(bào)dll無法找到的錯(cuò)誤而使得程序無法運(yùn)行。

編譯時(shí)需要加入import library,。

      2,、若調(diào)用的dll很多,載入應(yīng)用程序的速度就會很慢,。

不同的c++編譯器靜態(tài)載入的方式也不一樣,。

 

二、Explicit Linking(顯式連接)

          所謂Explicit Link(顯式連接)又叫動態(tài)載入,,使用dll的可執(zhí)行文件必須明確調(diào)用載入和御載dll的函數(shù)調(diào)用(Function Call),,并且存取dll的輸出函數(shù)。用戶端必須通過函數(shù)聲明調(diào)用函數(shù),。

          可執(zhí)行文件可以使用任何一種連接方式的相同低dll,。并且,,這些機(jī)制之間并不會相互排斥,因此,,當(dāng)一個(gè)可執(zhí)行文件隱式的連接dll時(shí),,其他程序還可以顯示地連接它。

 

      動態(tài)載入方式的優(yōu)缺點(diǎn):

       1,、dll只有需要時(shí)才載入內(nèi)存中,,這樣可以更有效地使用存儲空間。

      2,、應(yīng)用程序載入速度較隱式連接較快,,因?yàn)楫?dāng)程序開始載入時(shí)并不需要把dll載入到程序中。

      3,、編譯時(shí)不需要額外的import library,。


      4、可以讓用戶個(gè)清楚地知道dll的載入流程,。     


      缺點(diǎn)就是必須多寫一點(diǎn)代碼,。 

      動態(tài)載入基本流程

      必須使用LoadLibrary這個(gè)Windows API來手動載入DLL,并使用GetProcessAddress來取得所需要使用的函數(shù)的函數(shù)指針,,最后用FreeLibrary將DLL釋放,。所以學(xué)會動態(tài)載入DLL時(shí),必須先知道函數(shù)指針的用法,。






    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多