DLL的Export和Import

gudesheng發表於2008-01-03
 
DLLexport是指將DLL中的函式和資料輸出到其它程式中,以供其使用。DLLimport是指使用DLL的程式引入DLL中的函式和資料。
 
DLLexport
 
DLL中包含有一個表,稱為export table(以下簡稱ET),其中包含了DLL中可以被外部程式使用的所有函式和資料的名字。只有記錄在ET中的函式和資料才可以被外部程式所使用(如果沒有.DEF檔案的話),其它所有沒有記錄在ET中的函式和資料都被視為是DLL私有的。因此,要將DLL中的函式和資料export只有兩個方法:
 
l         DLL建立一個.DEF檔案(模組定義檔案),並在buildDLL時使用這個.DEF檔案。使用這種方法使你可以將函式按序號export
 
l         DLL中想要export的函式和資料定義前新增_declspecdllexport)關鍵字(對於函式和變數定義,加在最前面;對於class定義,加在class關鍵字後),這樣該函式和資料就會被新增到ET中。使用這種方法函式將按名字export
 
WINDOWS下,無論使用上述的哪一種方法,都必須要將export函式宣告為_stdcall
 
關於CC++的相容問題
 
如果要寫CC++相容的DLL,因為在CC++下使用了不同的名字修飾規則以及不同的呼叫約定,所以,如果DLL是用C編寫和編譯的,則在用於C++模組時,函式的宣告前應加上extern “C”關鍵字,以告訴LINKER使用C外部連線(即按照C名字修飾規則在外部模組中尋找函式);反之,如果DLL是用C++編寫和編譯的,則在用於C模組時,函式的宣告前要加上extern “C++”關鍵字。VC++通過_cplusplus巨集來標識C++程式。如果是C++程式,VC編譯器就會為你定義_cplusplus巨集。所以在DLL中可以使用如下的技術來解決相容問題:
 
#ifdef _cplusplus
 
extern “C” {
 
#endif
 
// 將所有的函式宣告放在這裡
 
#ifdef _cplusplus
 
}
 
#endif
 
.DEF檔案
 
         .DEF檔案是包含了DLL模組資訊的文字檔案。其語法結構如下:
 
         LIBRARY         DLL file name
 
         DESCRIPTION         “descriptions”
 
         EXPORTS
 
                  Function names        @nums
 
         LIBRARY為關鍵字,後面緊跟關聯的DLL檔名;DESCRIPTION後為可選的描述字串,除了增加可讀性外沒什麼用處;EXPORTS後是export函式的列表,首先是函式名,然後是@符號,後緊跟一十進位制數,為該函式的標號,範圍從1DLLexport函式的總數。注意,這裡的名字是經過名字修飾後的函式名字,如果是DLL是用C++寫的話,那麼就很鬱悶了。
 
         如果是擴充套件DLLextension DLL),並且通過.DEF檔案export,那麼必須在標頭檔案中新增如下的語句:
            #undef AFX_DATA
               #define AFX_DATA AFX_EXT_DATA
               // 標頭檔案中的其它內容
               #undef AFX_DATA
               #define AFX_DATA
 
這些語句確保一些MFC中內部使用的變數被export到外部程式中。例如:在class中通過DECLARE_DYNAMIC獲得的CRuntimeClass變數。否則DLL將會無法正確地編譯和連線,或外部程式無法正確連線到該DLL
 
DLLimport
 
         外部程式的一個原始檔要使用DLL中的函式和資料,就像要使用外部模組中的函式和資料一樣,必須首先給出函式和資料的宣告;對於class則要給出類的定義。這就稱為import。對於VC編譯器,Import DLL的函式和資料的語法與一般的宣告類似,但要在前面加上_declspecdllimport)關鍵字(對於函式和變數宣告,加在最前面;對於class定義,加在class關鍵字後)。如果是函式,則該關鍵字是可選的,但使用該關鍵字有可能會導致編譯器產生較高效的程式碼。但對於變數和class,則必須使用該關鍵字。
 
         通過使用以下的技術,可以編寫在.LIB檔案和外部程式原始檔通用的標頭檔案:
               #ifdef _EXPORTING
               #define CLASS_DECLSPEC    __declspec(dllexport)
           #else
                  #define CLASS_DECLSPEC    __declspec(dllimport)
               #endif
 
編譯器提供的_EXPORTING巨集可以用於標式該原始檔來自DLL檔案還是外部程式。 


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1477797


相關文章