程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> DLL(Dynamic Link Libraries)全面剖析(4)

DLL(Dynamic Link Libraries)全面剖析(4)

編輯:vc教程
關於DLL的函數

  動態鏈接庫中定義有兩種函數:導出函數(export function)和內部函數(internal function)。導出函數可以被其它模塊調用,內部函數在定義它們的DLL程序內部使用。

  輸出函數的方法有以下幾種:

  1、傳統的方法

  在模塊定義文件的 EXPORT 部分指定要輸入的函數或者變量。語法格式如下:

entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE] 

  其中:

  entryname 是輸出的函數或者數據被引用的名稱; internalname 同 entryname; @ordinal 表示在輸出表中的順序號(index); NONAME 僅僅在按順序號輸出時被使用(不使用 entryname ); DATA 表示輸出的是數據項,使用 DLL 輸出數據的程序必須聲明該數據項為 _declspec(DLLimport)。

  上述各項中,只有 entryname 項是必須的,其他可以省略。

  對於"C"函數來說,entryname 可以等同於函數名;但是對 "C++" 函數(成員函數、非成員函數)來說,entryname 是修飾名。可以從 .map 映像文件中得到要輸出函數的修飾名,或者使用DUMPBIN /SYMBOLS 得到,然後把它們寫在 .def 文件的輸出模塊。DUMPBIN 是VC提供的一個工具。

  如果要輸出一個 "C++" 類,則把要輸出的數據和成員的修飾名都寫入 .def 模塊定義文件。

  2、在命令行輸出

  對鏈接程序 LINK 指定 /EXPORT 命令行參數,輸出有關函數。

  3、使用 MFC 提供的修飾符號 _declspec(DLLexport)

  在要輸出的函數、類、數據的聲明前加上 _declspec(DLLexport) 修飾符表示輸出。__declspec(DLLexport) 在 C 調用約定、C 編譯情況下可以去掉輸出函數名的下劃線前綴。extern "C" 使得在 C++ 中使用 C 編譯方式成為可能。在"C++"下定義"C"函數需要加 extern "C" 關鍵詞。用 extern "C" 來指明該函數使用 C 編譯方式。輸出的 "C" 函數可以從 "C" 代碼裡調用。

  例如,在一個 C++ 文件中,有如下函數:

extern "C" {void __declspec(DLLexport) __cdecl Test(int var);} 

  其輸出函數名為:Test

  MFC提供了一些宏,就有這樣的作用。

AFX_CLASS_IMPORT:__declspec(DLLexport) AFX_API_IMPORT:__declspec(DLLexport) AFX_DATA_IMPORT:__declspec(DLLexport) AFX_CLASS_EXPORT:__declspec(DLLexport) AFX_API_EXPORT:__declspec(DLLexport) AFX_DATA_EXPORT:__declspec(DLLexport) AFX_EXT_CLASS: #ifdef _AFXEXT 			AFX_CLASS_EXPORT 	    #else 			AFX_CLASS_IMPORT  AFX_EXT_API:#ifdef _AFXEXT 			 AFX_API_EXPORT 	  #else 			 AFX_API_IMPORT  AFX_EXT_DATA:#ifdef _AFXEXT 			 AFX_DATA_EXPORT 	   #else 			 AFX_DATA_IMPORT 

  像 AFX_EXT_CLASS 這樣的宏,如果用於 DLL 應用程序的實現中,則表示輸出(因為_AFX_EXT被定義,通常是在編譯器的標識參數中指定該選項 /D_AFX_EXT);如果用於使用DLL的應用程序中,則表示輸入(_AFX_EXT沒有定義)。   要輸出整個的類,對類使用_declspec(_DLLexpot);要輸出類的成員函數,則對該函數使用_declspec(_DLLexport)。如:

class AFX_EXT_CLASS CTextDoc : public CDocument { 	… } extern "C" AFX_EXT_API void WINAPI InitMYDLL(); 

  這幾種方法中,最好采用第三種,方便好用;其次是第一種,如果按順序號輸出,調用效率會高些;最次是第二種。

模塊定義文件(.DEF)

  模塊定義文件(.DEF)是一個或多個用於描述 DLL 屬性的模塊語句組成的文本文件,每個DEF文件至少必須包含以下模塊定義語句:

  • 第一個語句必須是LIBRARY語句,指出DLL的名字;
  • EXPORTS 語句列出被導出函數的名字;將要輸出的函數修飾名羅列在 EXPORTS 之下,這個名字必須與定義函數的名字完全一致,如此就得到一個沒有任何修飾的函數名了。
  • 可以使用DESCRIPTION語句描述DLL的用途(此句可選);
  • ";"對一行進行注釋(可選)。
  • DLL程序和調用其輸出函數的程序的關系

      1、DLL與進程、線程之間的關系

  • DLL模塊被映射到調用它的進程的虛擬地址空間。
  • DLL使用的內存從調用進程的虛擬地址空間分配,只能被該進程的線程所訪問。
  • DLL的句柄可以被調用進程使用;調用進程的句柄可以被DLL使用。
  • DLL使用調用進程的棧。
  •   2、關於共享數據段

      DLL定義的全局變量可以被調用進程訪問;DLL可以訪問調用進程的全局數據。使用同一DLL的每一個進程都有自己的DLL全局變量實例。如果多個線程並發訪問同一變量,則需要使用同步機制;對一個DLL的變量,如果希望每個使用DLL的線程都有自己的值,則應該使用線程局部存儲(TLS,Thread Local Strorage)。   在程序裡加入預編譯指令,或在開發環境的項目設置裡也可以達到設置數據段屬性的目的.必須給這些變量賦初值,否則編譯器會把沒有賦初始值的變量放在一個叫未被初始化的數據段中。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved