日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态链接概述

發(fā)布時(shí)間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态链接概述 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

動(dòng)態(tài)鏈接庫概述
相關(guān)函數(shù)
動(dòng)態(tài)鏈接庫編程
dumpbin工具

(本章節(jié)中例子都是用 VS2005 編譯調(diào)試的)


動(dòng)態(tài)鏈接概述

?

說明

所謂動(dòng)態(tài)鏈接,就是把一些經(jīng)常會(huì)共用的代碼(靜態(tài)鏈接的OBJ程序庫)制作成DLL檔,當(dāng)可執(zhí)行文件調(diào)用到DLL檔內(nèi)的函數(shù)時(shí),windows操作系統(tǒng)才會(huì)把DLL檔加載存儲(chǔ)器內(nèi),DLL檔本身的結(jié)構(gòu)就是可執(zhí)行文件,當(dāng)程序需求函數(shù)才進(jìn)行鏈接.通過動(dòng)態(tài)鏈接方式,存儲(chǔ)器浪費(fèi)的情形將可大幅降低.

DLL的文檔格式與視窗EXE文檔一樣——也就是說,等同于32位視窗的可移植執(zhí)行文檔(PE)和16位視窗的New Executable(NE).作為EXE格式,DLL可以包括源代碼、數(shù)據(jù)和資源的多種組合.

在使用動(dòng)態(tài)庫的時(shí)候,往往提供兩個(gè)文件:一個(gè)引入庫(LIB)和一個(gè)動(dòng)態(tài)鏈接庫(DLL).引入庫(LIB)包含被動(dòng)態(tài)連接庫(DLL)所導(dǎo)出的函數(shù)和變量的符號(hào)名,動(dòng)態(tài)連接庫(DLL)包含實(shí)際的函數(shù)和數(shù)據(jù).在編譯鏈接可執(zhí)行文件時(shí),只需要鏈接引入庫(LIB),動(dòng)態(tài)連接庫(DLL)中的函數(shù)代碼和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件中,在運(yùn)行的時(shí)候,再去加載DLL,訪問動(dòng)態(tài)鏈接庫(DLL)中導(dǎo)出的函數(shù).

動(dòng)態(tài)鏈接庫(DLL)通常都不能直接運(yùn)行,也不能接收消息.它們是一些獨(dú)立的文件,其中包含能被可執(zhí)行程序或其它動(dòng)態(tài)連接庫(DLL)調(diào)用來完成某項(xiàng)工作的函數(shù).只有在其它模塊調(diào)用動(dòng)態(tài)鏈接庫(DLL)中的函數(shù)時(shí),它才發(fā)揮作用.但是動(dòng)態(tài)連接庫(DLL)被多進(jìn)程調(diào)用時(shí)候,動(dòng)態(tài)鏈接庫(DLL)中進(jìn)程訪問到動(dòng)態(tài)鏈接庫(DLL)的成員時(shí),系統(tǒng)會(huì)為它開辟一個(gè)新的數(shù)據(jù)成員頁面給訪問進(jìn)程提供單獨(dú)的動(dòng)態(tài)連接庫(DLL)數(shù)據(jù)區(qū).
  

特征(來自維基百科此處為鏈接)

  • 內(nèi)存管理

    在Win32中,DLL文檔按照片段(sections)進(jìn)行組織.每個(gè)片段有它自己的屬性,如可寫或是只讀、可執(zhí)行(代碼)或者不可執(zhí)行(數(shù)據(jù))等等.
    DLL代碼段通常被使用這個(gè)DLL的進(jìn)程所共享;也就是說它們?cè)谖锢韮?nèi)存中占據(jù)一個(gè)地方,并且不會(huì)出現(xiàn)在頁面文檔中.如果代碼段所占據(jù)的物理內(nèi)存被收回,它的內(nèi)容就會(huì)被放棄,后面如果需要的話就直接從DLL文檔重新加載.
    與代碼段不同,DLL的數(shù)據(jù)段通常是私有的;也就是說,每個(gè)使用DLL的進(jìn)程都有自己的DLL數(shù)據(jù)副本.作為選擇,數(shù)據(jù)段可以設(shè)置為共享,允許通過這個(gè)共享內(nèi)存區(qū)域進(jìn)行進(jìn)程間通信.但是,因?yàn)橛脩魴?quán)限不能應(yīng)用到這個(gè)共享DLL內(nèi)存,這將產(chǎn)生一個(gè)安全漏洞;也就是一個(gè)進(jìn)程能夠破壞共享數(shù)據(jù),這將導(dǎo)致其它的共享進(jìn)程異常.例如,一個(gè)使用訪客賬號(hào)的進(jìn)程將可能通過這種方式破壞其它運(yùn)行在特權(quán)賬號(hào)的進(jìn)程.這是在DLL中避免使用共享片段的一個(gè)重要原因.
    當(dāng)DLL被如UPX這樣一個(gè)可執(zhí)行的packer壓縮時(shí),它的所有代碼段都標(biāo)記為可以讀寫并且是非共享的.可以讀寫的代碼段,類似于私有數(shù)據(jù)段,是每個(gè)進(jìn)程私有的并且被頁面文檔備份.這樣,壓縮DLL將同時(shí)增加內(nèi)存和磁盤空間消耗,所以共享DLL應(yīng)當(dāng)避免使用壓縮DLL.

  • 符號(hào)解析和綁定

    DLL輸出的每個(gè)函數(shù)都由一個(gè)數(shù)字序號(hào)唯一標(biāo)識(shí),也可以由可選的名字標(biāo)識(shí).同樣,DLL引入的函數(shù)也可以由序號(hào)或者名字標(biāo)識(shí).對(duì)于內(nèi)部函數(shù)來說,只輸出序號(hào)的情形很常見.對(duì)于大多數(shù)視窗API函數(shù)來說名字是不同視窗版本之間保留不變的;序號(hào)有可能會(huì)發(fā)生變化.這樣,我們不能根據(jù)序號(hào)引用視窗API函數(shù).
    按照序號(hào)引用函數(shù)并不一定比按照名字引用函數(shù)性能更好:DLL輸出表是按照名字排列的,所以對(duì)半查找可以用來在在這個(gè)表中根據(jù)名字查找這個(gè)函數(shù).另外一方面,只有線性查找才可以用于根據(jù)序號(hào)查找函數(shù).
    將一個(gè)可執(zhí)行文件綁定到一個(gè)特定版本的DLL也是可能的,這也就是說,可以在編譯時(shí)解析輸入函數(shù)(imported functions)的地址.對(duì)于綁定的輸入函數(shù),連結(jié)工具保存了輸入函數(shù)綁定的DLL的時(shí)間戳和校驗(yàn)和.在運(yùn)行時(shí)Windows檢查是否正在使用同樣版本的庫,如果是的話,Windows將繞過處理輸入函數(shù);否則如果庫與綁定的庫不同,Windows將按照正常的方式處理輸入函數(shù).
    綁定的可執(zhí)行文件如果運(yùn)行在與它們編譯所用的環(huán)境一樣,函數(shù)調(diào)用將會(huì)較快,如果是在一個(gè)不同的環(huán)境它們就等同于正常的調(diào)用,所以綁定輸入函數(shù)沒有任何的缺點(diǎn).例如,所有的標(biāo)準(zhǔn)Windows應(yīng)用程序都綁定到它們各自的Windows發(fā)布版本的系統(tǒng)DLL.將一個(gè)應(yīng)用程序輸入函數(shù)綁定到它的目的環(huán)境的好機(jī)會(huì)是在應(yīng)用程序安裝的過程.

  • 運(yùn)行時(shí)顯式鏈接

    對(duì)每個(gè)DLL來說,Windows存儲(chǔ)了一個(gè)全局計(jì)數(shù)器,每多一個(gè)進(jìn)程使用便多額外一個(gè).LoadLibrary與FreeLibrary指令影響每一個(gè)進(jìn)程內(nèi)含的計(jì)數(shù)器;動(dòng)態(tài)鏈接則不影響.因此借由調(diào)用FreeLibrary多次,從存儲(chǔ)器反加載一DLL是很重要的.一個(gè)進(jìn)程可以從它自己的VAS注銷此計(jì)數(shù)器.
    DLL文檔能夠在運(yùn)行時(shí)使用LoadLibrary(或者LoadLibraryEx)API函數(shù)進(jìn)行顯式調(diào)用,這個(gè)的過程微軟簡(jiǎn)單地稱為運(yùn)行時(shí)動(dòng)態(tài)調(diào)用.API函數(shù)GetProcAddress根據(jù)查找輸出名稱符號(hào)、FreeLibrary卸載DLL.這些函數(shù)類似于POSIX標(biāo)準(zhǔn)API中的dlopen、dlsym、和dlclose.
    注意微軟簡(jiǎn)單稱為運(yùn)行時(shí)動(dòng)態(tài)鏈接的運(yùn)行時(shí)隱式鏈接,如果不能找到鏈接的DLL文檔,Windows將提示一個(gè)錯(cuò)誤消息并且調(diào)用應(yīng)用程序失敗.應(yīng)用程序開發(fā)人員不能通過編譯鏈接來處理這種缺少DLL文檔的隱式鏈接問題.另外一方面,對(duì)于顯式鏈接,開發(fā)人員有機(jī)會(huì)提供一個(gè)完善的出錯(cuò)處理機(jī)制.
    運(yùn)行時(shí)顯式鏈接的過程在所有語言中都是相同的,因?yàn)樗蕾囉赪indows API而不是語言結(jié)構(gòu).

與靜態(tài)鏈接庫的區(qū)別

靜態(tài)庫本身就包含了實(shí)際執(zhí)行代碼、符號(hào)表等等,而對(duì)于導(dǎo)入庫而言,其實(shí)際的執(zhí)行代碼位于動(dòng)態(tài)庫中,動(dòng)態(tài)鏈接庫只包含了地址符號(hào)表等,確保程序找到對(duì)應(yīng)函數(shù)的一些基本地址信息.

Windows 下 3 個(gè)重要的 DLL

Windows API中的所有函數(shù)都包含在DLL中。其中有3個(gè)最重要的DLL

  • Kernel32.dll,它包含用于管理內(nèi)存、進(jìn)程和線程的各個(gè)函數(shù)
  • User32.dll,它包含用于執(zhí)行用戶界面任務(wù)(如窗口的創(chuàng)建和消息的傳送)的各個(gè)函數(shù)
  • GDI32.dll,它包含用于畫圖和顯示文本的各個(gè)函數(shù)

動(dòng)態(tài)鏈接庫的優(yōu)點(diǎn)

  • 可以采用多種編程語言來編寫

    我們可以采用自己熟悉的開發(fā)語言編寫DLL,然后由其他語言編寫的可執(zhí)行程序來調(diào)用這些DLL.例如,可以利用VB來編寫程序界面,然后利用VC++或Delphi編寫的完成程序作業(yè)邏輯的DLL

  • 增強(qiáng)產(chǎn)品的功能

    在發(fā)布產(chǎn)品時(shí),可以發(fā)布產(chǎn)品功能實(shí)現(xiàn)的動(dòng)態(tài)鏈接庫規(guī)范,讓其他公司或個(gè)人遵照這種規(guī)范開發(fā)自己的DLL,以取代產(chǎn)品原有的DLL.讓產(chǎn)品調(diào)用新的DLL,從而實(shí)現(xiàn)功能的增強(qiáng),在實(shí)際工作中,我們看到許多產(chǎn)品都提供了界面插件功能,允許用戶動(dòng)態(tài)地更換程序的界面,這就可以通過更換界面DLL來實(shí)現(xiàn)

  • 提供二次開發(fā)的平臺(tái)

    在銷售產(chǎn)品時(shí),可以采用DLL的形式提供一個(gè)二次開發(fā)的平臺(tái),讓用戶可以利用該DLL調(diào)用其中實(shí)現(xiàn)的功能,編寫符合自己業(yè)務(wù)需要的產(chǎn)品,從而實(shí)現(xiàn)二次開發(fā)

  • 簡(jiǎn)化項(xiàng)目管理

    在一個(gè)大型項(xiàng)目開發(fā)中,通常都是由多個(gè)項(xiàng)目小組同時(shí)開發(fā),如果采用串行開發(fā),則效率非常低的,我們可以將項(xiàng)目細(xì)分,將不同功能交由各個(gè)項(xiàng)目小組以多個(gè)DLL方式實(shí)現(xiàn),這樣各個(gè)項(xiàng)目小組就可以同時(shí)進(jìn)行開發(fā)了

  • 可以節(jié)省磁盤空間和內(nèi)存

    如果多個(gè)應(yīng)用程序需要訪問同樣的功能,那么可以將該功能以DLL的形式提供,這樣在機(jī)器上只需要存在一份該DLL文件就可以了,從而節(jié)省了磁盤空間.另外如果多個(gè)應(yīng)用程序使用同一個(gè)DLL,該DLL的頁面只需要放入內(nèi)存一次,所有的應(yīng)用程序就都可以共享它的頁面了.這樣,內(nèi)存的使用將更加有效
    如下圖所示就是一個(gè)動(dòng)態(tài)鏈接庫被兩個(gè)進(jìn)程調(diào)用時(shí)的內(nèi)存示意圖,當(dāng)進(jìn)程被加載時(shí),系統(tǒng)為它分配4GB的地址空間,接著分析該可執(zhí)行模塊,找到該程序要調(diào)用那些DLL模塊,然后系統(tǒng)搜索這些DLL,找到后就加載它們,并為它們分配虛擬的內(nèi)存空間,最后將DLL的頁面映射到進(jìn)程的地址空間.,從此可以導(dǎo)致多個(gè)程序中共享DLL的同一份代碼,這樣就可以節(jié)省空間

  • 有助于資源的共享

    DLL可以包含對(duì)話框模板,字符串,圖標(biāo)和位圖等多種資源,多個(gè)應(yīng)用程序可以使用DLL來共享這些資源.在實(shí)際工作中,可以寫一個(gè)純資源的動(dòng)態(tài)鏈接庫文件,供其他應(yīng)用程序訪問

  • 有助于實(shí)現(xiàn)應(yīng)用程序的本地化

    如果產(chǎn)品需要提供多語言版本,那么就可以使用DLL來支持多語言,可以為每種語言創(chuàng)建一個(gè)只支持這種語言的動(dòng)態(tài)鏈接庫


相關(guān)函數(shù)

顯示相關(guān)函數(shù)

?


編寫動(dòng)態(tài)連接庫

本程序使用的編譯環(huán)境是VS2005,如果是使用VC6.0環(huán)境的可以去網(wǎng)上找孫鑫關(guān)于VC的視頻,視頻第19講講的就是動(dòng)態(tài)連接庫編寫.

[編寫動(dòng)態(tài)鏈接庫][加載動(dòng)態(tài)鏈接庫][C++命名改編][調(diào)用約定]

?

編寫動(dòng)態(tài)鏈接庫

建立DLL項(xiàng)目

  • Win32 -> Win32項(xiàng)目 -> DLL(D)
  • MFC -> MFC DLL

生成導(dǎo)出函數(shù),類,成員函數(shù)

  • 生成導(dǎo)出函數(shù):  在函數(shù)前添加_declspec(dllexport)[導(dǎo)出標(biāo)示符]生成導(dǎo)出函數(shù),
  • 生成導(dǎo)出類:  在class后類名前添加_declspec(dllexport)[[導(dǎo)出標(biāo)示符]這樣就可以導(dǎo)出整個(gè)類,但是訪問類的函數(shù)時(shí)候,仍然受限于函數(shù)自身的范圍權(quán)限.也就是說,如果該函數(shù)訪問權(quán)限是private或protect的話,那么外部程序仍然無法訪問這個(gè)函數(shù)
  • 生成導(dǎo)出成員函數(shù):  在成員函數(shù)的返回類型后在函數(shù)的函數(shù)名前面加_declspec(dllexport)

代碼示例(例子鏈接)

?

加載動(dòng)態(tài)連接庫

隱式鏈接方式加載動(dòng)態(tài)庫(例子鏈接)

步驟:

  • 加載dll.lib文件
    • VC6.0:      點(diǎn)擊 Project/Settings后對(duì)話框下Link的Object/library modules下添加dll的lib文件
    • VS/VC6.0:   ? ?在文件中利用#pragma comment(lib,"鏈接庫地址")
  • 加載dll.dll文件?
      把dll文件放在下面路徑的一種中
    • 程序目錄
    • 當(dāng)前目錄
    • 系統(tǒng)目錄
    • path環(huán)境變量中列出的路徑中
  • 利用extern / _declspec(dllimport)[導(dǎo)出標(biāo)示符]聲明動(dòng)態(tài)鏈接庫的函數(shù)
    • _declspec(dllimport)  可以調(diào)用dll中非導(dǎo)出函數(shù)[沒有_declspec(dllexport)的函數(shù)]
    • extern         ?只能調(diào)用dll中導(dǎo)出函數(shù)[有_declspec(dllexport)的函數(shù)]
    與使用extern關(guān)鍵字這種方式相比,使用_declspec(dllimport)標(biāo)識(shí)符聲明外部函數(shù)時(shí),它將告訴編譯器該函數(shù)是從動(dòng)態(tài)鏈接庫中引用的,編譯器可以生成運(yùn)行效率更高的代碼,因此,如果是調(diào)用的函數(shù)來自動(dòng)態(tài)鏈接庫DLL中,應(yīng)該采用這種方式調(diào)用函數(shù)

流程圖:

顯示加載方式加載DLL(例子鏈接)

步驟:

  • 將最新的dll文件復(fù)制到以下路徑中
    • 程序目錄
    • 當(dāng)前目錄
    • 系統(tǒng)目錄
    • path環(huán)境變量中列出的路徑中
  • 調(diào)用LoadLibrary,加載動(dòng)態(tài)庫
  • 聲明需要的動(dòng)態(tài)鏈接的函數(shù)指針類型(此處可以要可以不要,這樣只是方便以后定義相關(guān)函數(shù)指針) //例如下面要調(diào)用動(dòng)態(tài)鏈接庫中的 int max_dll(int a,int b) 函數(shù) //所以需要定義相關(guān)類型的指針聲明 typedef int (/*_stdcall*/ *INTMAX)(int a,int b);//以后就可以用INTMAX來定義相關(guān)指針如 INTMAX pMaxInt;
  • 獲得函數(shù)地址GetProcAddress
  • 調(diào)用FreeLibrary釋放動(dòng)態(tài)鏈接庫

流程圖:

兩種加載方式的比較

動(dòng)態(tài)加載和隱式鏈接這兩種加載DLL的方式各有優(yōu)點(diǎn).如果采用動(dòng)態(tài)加載的方式,那么可以在需要加載時(shí)才加載DLL.而隱式鏈接方式實(shí)現(xiàn)起來比較簡(jiǎn)單,在編寫客戶端代碼時(shí)就可以把鏈接工作做好,在程序中可以隨時(shí)調(diào)用DLL導(dǎo)出的函數(shù),但是訪問十多個(gè)DLL,如果都采用隱式鏈接的方式鏈接加載他們的話,那么在啟動(dòng)程序時(shí)候,這些DLL都需要加載到內(nèi)存中,并映射到調(diào)用進(jìn)程的地址空間,這樣將加大啟動(dòng)程序的時(shí)間,而且,一般來說,在程序運(yùn)行過程中只是在某個(gè)條件滿足時(shí)候,這時(shí)才會(huì)訪問某個(gè)DLL中的某個(gè)函數(shù),其他情況下都不需要訪問這些DLL,但是,這時(shí)所有的DLL都被已經(jīng)加載到內(nèi)存中,資源浪費(fèi)會(huì)比較嚴(yán)重,這種情況下,就可以采用動(dòng)態(tài)加載DLL技術(shù),也就是說,在需要時(shí),DLL才會(huì)被加載到內(nèi)存中,并被映射到進(jìn)程的地址空間中,有一點(diǎn)需要說明的是,實(shí)際上,采用隱式鏈接的方式訪問DLL時(shí),在啟動(dòng)時(shí)也是通過調(diào)用LoadLibrary函數(shù)加載到該進(jìn)程需要的動(dòng)態(tài)鏈接庫的

?

代碼示例

動(dòng)態(tài)連接庫源程序代碼

程序源碼

View Code

隱式調(diào)用動(dòng)態(tài)鏈接

程序源碼

View Code

運(yùn)行結(jié)果

顯示調(diào)用動(dòng)態(tài)鏈接庫

程序源碼

View Code

運(yùn)行結(jié)果


dumpbin 工具

[概述][使用步驟][C++命名改編][調(diào)用約定]

?

概述

用途

查看dll與exe相關(guān)導(dǎo)入導(dǎo)出函數(shù)信息

dumpbin程序的文件位置

  • VC6.0:  VC98 \ bin
  • VS2005:  Microsoft Visual Studio 8\VC\bin

相關(guān)參數(shù)

  • -exports 文件名.dll ?   (查看導(dǎo)出函數(shù)和導(dǎo)出類)
  • -imports 文件名.exe   (查看導(dǎo)入函數(shù))

設(shè)置VC++使用環(huán)境信息

VCVAR32.bat 建立VC++使用環(huán)境信息,但是注意當(dāng)在命令行界面下執(zhí)行VCVARS32.bat文件后,該文件所設(shè)置的環(huán)境信息只是在當(dāng)前命令行窗口生效.如果關(guān)閉該窗口,再次啟動(dòng)一個(gè)新的命令行窗口后,仍需要運(yùn)行VCVAR32.bat文件

?

使用步驟

  • 以上面的DLL源程序?yàn)槔?做個(gè)使用說明,先打開控制臺(tái)(如下圖)
  • 然后,把建立VC++使用環(huán)境信息,把VCVAR32.bat(批處理的位置和dumpbin一樣)拖到控制臺(tái)界面中(如下圖).
  • 然后回車,便建立好了VC++使用環(huán)境信息(如下圖).這樣就可以是用 dumpbin 這個(gè)命名了.
  • 然后切換到工程目錄中的 debug 或 release 中去.(如下圖)
  • 接著用 dumpbin 查看工程生成的 dll.dll 動(dòng)態(tài)鏈接庫的導(dǎo)出函數(shù)(如下圖)(注意:這個(gè)函數(shù)必須有_declspec(dllexport)修飾,否則在這里是看不到).

流程圖如下:

?

C++名字改編(C++名字粉碎)

在上面使用 dumpbin 程序查看 dll.dll 的導(dǎo)出函數(shù)發(fā)現(xiàn)函數(shù)名有點(diǎn)奇怪,我們定義的函數(shù)名max_dll兩個(gè)重載函數(shù)名在這里變成了 ?max_dll@@YAHHH@Z?與 ?max_dll@@YANNN@Z,因?yàn)?span style="color:#ff0000">C++支持函數(shù)重載,對(duì)于重載的多個(gè)函數(shù)來說,其函數(shù)名都是一樣的,為了加以區(qū)分,在編譯連接時(shí),C++會(huì)按照自己的規(guī)則篡改函數(shù)名字,這一過程為"名字改編".有的書中也稱為"名字粉碎".不同的C++編譯器會(huì)采用不同的規(guī)則進(jìn)行名字改編,這個(gè)的話,利用不同的C++編譯器生成的程序在調(diào)用對(duì)方提供的函數(shù)時(shí),可能會(huì)出現(xiàn)問題

解決名字改變問題

第一種

  • 聲明:
    • 在定義導(dǎo)出函數(shù)時(shí),需要加上限定符: extern"C" (雙引號(hào)中的C一定要大寫)
  • 注意:
    • 使動(dòng)態(tài)鏈接庫文件在鏈接時(shí),導(dǎo)出函數(shù)的函數(shù)名稱不發(fā)生改變.
    • 利用 extern "C" 可以解決 C++ 和 C 語言之間相互調(diào)用時(shí)函數(shù)命名的問題.但是這種方法有一個(gè)缺陷,就是不能用于導(dǎo)出一個(gè)類成員函數(shù),只能導(dǎo)出全局函數(shù)這種情況
    • 如果導(dǎo)出函數(shù)的調(diào)用約定發(fā)生了改變,那么即使使用了限定符: extern "C" ,該函數(shù)的名字仍然會(huì)發(fā)生改編.
    • 記得導(dǎo)出和導(dǎo)入都要加入 extern "C" 否則在調(diào)用動(dòng)態(tài)鏈接庫時(shí)候會(huì)發(fā)生找不到函數(shù)這個(gè)現(xiàn)象.

代碼樣例:

利用 extern"C" 解決名字改編

動(dòng)態(tài)連接庫程序源碼

View Code

主程序源碼

View Code

利用 dumpbin 查看命名

?

調(diào)用約定

四種調(diào)用方式:

__cdecl

__cdecl調(diào)用約定又稱為 C 調(diào)用約定,是 C/C++ 語言缺省的調(diào)用約定。參數(shù)按照從右至左的方式入棧,函數(shù)本身不清理?xiàng)?#xff0c;此工作由調(diào)用者負(fù)責(zé),返回值在EAX中。由于由調(diào)用者清理?xiàng)?#xff0c;所以允許可變參數(shù)函數(shù)存在,如int sprintf(char* buffer,const char* format,...);。

__stdcall

__stdcall 很多時(shí)候被稱為 pascal 調(diào)用約定。pascal 語言是早期很常見的一種教學(xué)用計(jì)算機(jī)程序設(shè)計(jì)語言,其語法嚴(yán)謹(jǐn)。參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在EAX中。

__fastcall

顧名思義,__fastcall 的特點(diǎn)就是快,因?yàn)樗ㄟ^ CPU 寄存器來傳遞參數(shù)。他用 ECX 和 EDX 傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在 EAX 中。

__thiscall

這是 C++ 語言特有的一種調(diào)用方式,用于類成員函數(shù)的調(diào)用約定。如果參數(shù)確定,this 指針存放于 ECX 寄存器,函數(shù)自身清理堆棧;如果參數(shù)不確定,this指針在所有參數(shù)入棧后再入棧,調(diào)用者清理?xiàng)!_thiscall 不是關(guān)鍵字,程序員不能使用。參數(shù)按照從右至左的方式入棧。

相關(guān)鏈接:

  • C/C++函數(shù)調(diào)用約定
  • 剖析VC++函數(shù)調(diào)用約定

代碼示例(編譯環(huán)境VS2005):

使用 extern "C" 時(shí)

動(dòng)態(tài)連接庫源碼:

View Code

用 dumpbin 查看導(dǎo)出函數(shù):

未使用 extern "C" 時(shí)

動(dòng)態(tài)連接庫源碼:

View Code

用 dumpbin 查看導(dǎo)出函數(shù):

?


總結(jié)

以上是生活随笔為你收集整理的动态链接概述的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。