關於DLL函數

一 關於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)。  
   
  在程序里加入預編譯指令,或在開發環境的項目設置裏也可以達到設置數據段屬性的目的.必須給  
  這些變量賦初值,否則編譯器會把沒有賦初始值的變量放在一個叫未被初始化的數據段中。  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章