电竞比分网-中国电竞赛事及体育赛事平台

分享

DLL中.def文件的使用

 求真我 2014-04-20

DLL中導(dǎo)出函數(shù)的聲明有兩種方式:一種為在函數(shù)聲明中加上__declspec(dllexport),這里不再舉例說(shuō)明;另外一種方式是采用模塊定義(.def) 文件聲明,.def文件為鏈接器提供了有關(guān)被鏈接程序的導(dǎo)出、屬性及其他方面的信息。


首先創(chuàng)建 一個(gè)DLL程序,.cpp中

  1. int __stdcall Add(int numa, int numb)  
  2. {  
  3.        return (numa + numb);  
  4. }  
  5.   
  6. int __stdcall Sub(int numa, int numb)  
  7. {  
  8.         return (numa - numb);  
  9. }  
  1. int __stdcall Add(int numa, int numb)  
  2. {  
  3.        return (numa + numb);  
  4. }  
  5.   
  6. int __stdcall Sub(int numa, int numb)  
  7. {  
  8.         return (numa - numb);  
  9. }  
 

然后創(chuàng)建一個(gè).def的文件,在里面加上

;DllTestDef.lib : 導(dǎo)出DLL函數(shù)
;作者:----
LIBRARY DllTestDef
EXPORTS
Add @ 1
Sub @ 2

最后創(chuàng)建一個(gè)測(cè)試程序:.cpp文件如下:

  1. #include <iostream>   
  2. #include <windows.h>   
  3.   
  4. using namespace std;  
  5.   
  6. typedef int (__stdcall *FUN)(int, int);  
  7. HINSTANCE hInstance;  
  8. FUN   fun;  
  9.   
  10. int main()  
  11. {  
  12.        hInstance = LoadLibrary("DLLTestDef.dll");  
  13.        if(!hInstance)  
  14.            cout << "Not Find this Dll" << endl;  
  15.        fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1));  
  16.        if (!fun)  
  17.        {  
  18.               cout << "not find this fun" << endl;  
  19.        }  
  20.        cout << fun(1, 2) << endl;  
  21.        FreeLibrary(hInstance);  
  22.        return 0;  
  23. }  
  1. #include <iostream>  
  2. #include <windows.h>  
  3.   
  4. using namespace std;  
  5.   
  6. typedef int (__stdcall *FUN)(int, int);  
  7. HINSTANCE hInstance;  
  8. FUN   fun;  
  9.   
  10. int main()  
  11. {  
  12.        hInstance = LoadLibrary("DLLTestDef.dll");  
  13.        if(!hInstance)  
  14.            cout << "Not Find this Dll" << endl;  
  15.        fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1));  
  16.        if (!fun)  
  17.        {  
  18.               cout << "not find this fun" << endl;  
  19.        }  
  20.        cout << fun(1, 2) << endl;  
  21.        FreeLibrary(hInstance);  
  22.        return 0;  
  23. }  



說(shuō)明:
.def文件的規(guī)則為:

  (1)LIBRARY語(yǔ)句說(shuō)明.def文件相應(yīng)的DLL;

  (2)EXPORTS語(yǔ)句后列出要導(dǎo)出函數(shù)的名稱(chēng)。可以在.def文件中的導(dǎo)出函數(shù)名后加@n,表示要導(dǎo)出函數(shù)的序號(hào)為n(在進(jìn)行函數(shù)調(diào)用時(shí),這個(gè)序號(hào)將發(fā)揮其作用);

  (3).def 文件中的注釋由每個(gè)注釋行開(kāi)始處的分號(hào) (;) 指定,且注釋不能與語(yǔ)句共享一行。

 

 

 

如果導(dǎo)出 C++ 文件中的函數(shù),必須將修飾名放到 .def 文件中,或者通過(guò)使用外部“C”定義具有標(biāo)準(zhǔn) C 鏈接的導(dǎo)出函數(shù)。如果需要將修飾名放到 .def 文件中,則可以通過(guò)使用 DUMPBIN 工具或 /MAP 鏈接器選項(xiàng)來(lái)獲取修飾名。請(qǐng)注意,編譯器產(chǎn)生的修飾名是編譯器特定的。如果將 Visual C++ 編譯器產(chǎn)生的修飾名放到 .def 文件中,則鏈接到 DLL 的應(yīng)用程序必須也是用相同版本的 Visual C++ 生成的,這樣調(diào)用應(yīng)用程序中的修飾名才能與 DLL 的 .def 文件中的導(dǎo)出名相匹配。

如果生成擴(kuò)展 DLL 并使用 .def 文件導(dǎo)出,則將下列代碼放在包含導(dǎo)出類(lèi)的頭文件的開(kāi)頭和結(jié)尾:


#undef AFX_DATA#define AFX_DATA AFX_EXT_DATA// <body of your header file>#undef AFX_DATA#define AFX_DATA這些代碼行確保內(nèi)部使用的 MFC 變量或添加到類(lèi)的變量是從擴(kuò)展 DLL 導(dǎo)出(或?qū)耄┑?。例如,?dāng)使用 DECLARE_DYNAMIC 派生類(lèi)時(shí),該宏擴(kuò)展以將 CRuntimeClass 成員變量添加到類(lèi)。省去這四行代碼可能會(huì)導(dǎo)致不能正確編譯或鏈接 DLL,或在客戶(hù)端應(yīng)用程序鏈接到 DLL 時(shí)導(dǎo)致錯(cuò)誤。

當(dāng)生成 DLL 時(shí),鏈接器使用 .def 文件創(chuàng)建導(dǎo)出 (.exp) 文件和導(dǎo)入庫(kù) (.lib) 文件。然后,鏈接器使用導(dǎo)出文件生成 DLL 文件。隱式鏈接到 DLL 的可執(zhí)行文件在生成時(shí)鏈接到導(dǎo)入庫(kù)。

請(qǐng)注意,MFC 本身使用 .def 文件從 MFCx0.dll 導(dǎo)出函數(shù)和類(lèi)。

在VC++中,如果生成DLL可以不使用.def文件。你只需要在VC++的函數(shù)定義前要加 __declspec(dllexport)修飾就可以了。但是使用__declspec(dllexport)和使用.def文件是有區(qū)別的。如果你的 DLL是提供給VC++用戶(hù)使用的,你只需要把編譯DLL時(shí)產(chǎn)生的.lib提供給用戶(hù),它可以很輕松地調(diào)用你的DLL。但是如果你的DLL是供VB、 PB、Delphi用戶(hù)使用的,那么會(huì)產(chǎn)生一個(gè)小麻煩。因?yàn)閂C++對(duì)于__declspec(dllexport)聲明的函數(shù)會(huì)進(jìn)行名稱(chēng)轉(zhuǎn)換,如下面的函數(shù):
   __declspec(dllexport) int __stdcall IsWinNT()
   會(huì)轉(zhuǎn)換為IsWinNT@0,這樣你在VB中必須這樣聲明:
   Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long
   @的后面的數(shù)由于參數(shù)類(lèi)型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉(zhuǎn)換,就要使用.def文件方式。
   EXPORTS后面的數(shù)可以不給,系統(tǒng)會(huì)自動(dòng)分配一個(gè)數(shù)。對(duì)于VB、PB、Delphi用戶(hù),通常使用按名稱(chēng)進(jìn)行調(diào)用的方式,這個(gè)數(shù)關(guān)系不大,但是對(duì)于使用.lib鏈接的VC程序來(lái)說(shuō),不是按名稱(chēng)進(jìn)行調(diào)用,而是按照這個(gè)數(shù)進(jìn)行調(diào)用的,所以最好給出。
  
   
  
  看來(lái)是def文件沒(méi)起到作用。最終發(fā)現(xiàn)需要將def文件配置到VC工程中的“鏈接器”的“模塊定義文件”中。
  
   
  
  問(wèn)題2:
  
  在def中增加幾個(gè)輸出函數(shù)定義后(這些函數(shù)本來(lái)已經(jīng)輸出,但沒(méi)有加到def文件中),發(fā)現(xiàn)某些以前編譯的程序執(zhí)行報(bào)錯(cuò)找不著函數(shù),但其他一些程序沒(méi)有報(bào)錯(cuò)??磥?lái)報(bào)錯(cuò)的程序連接時(shí)沒(méi)有使用lib文件,而沒(méi)報(bào)錯(cuò)的使用了;沒(méi)使用lib文件的通過(guò)hint定位函數(shù),所以總能找到但可能找錯(cuò)了——難怪聽(tīng)說(shuō)這個(gè)庫(kù)以前發(fā)生過(guò)函數(shù)調(diào)錯(cuò)的現(xiàn)象。
  
  增加了輸出函數(shù)卻忘了在def中增加定義,新手寫(xiě)的代碼又無(wú)人檢查,最嚴(yán)重的是后期的版本問(wèn)題。

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多