MFC的秘密:它的靜態庫和動態庫所在何處

來源:互聯網
上載者:User
1.Dependency Walker的第一道揭秘

在MFC中我們寫過很多靜態庫和動態庫。這些dll都依賴於MFC;然後我們又交給別人使用,使得它們被依賴。

細想一下,就可能會發現其中的不平衡。我們產生的非組件dll,要交給別人使用,必須提供h頭、lib庫和dll庫檔案;可是我們使用MFC的dll時,好像什麼也沒有設定,MFC不請自來的加入到我們的程式中。雖然知道這個世界,每個人其實並不是平等的;但是在電腦的世界,自由平等卻是第一法則。搞清MFC如何嵌入到我們的應用程式中,將一切黑暗中的操作暴露出來,將是我們的任務。

舉個例子,隨便用嚮導產生一個MFC 的對話方塊程式。裡面測試一個組件,然後調用wcslen求一個BSTR的長度。就是一個很簡單的exe;通過Dependency Walker就發現它依賴了很多dll。如下: 

    其中,這些函數何去何來,這個就是我們要弄清楚的秘密。

  • MFC42D.DLL
  • MSVCRTD.DLL
  • MFCO42D.DLL
  • OLEAUT32.DLL
2.MFC的組成

直接揭開謎底:MFC由四部分組成。可能這種說法不準確,應該說,VC的核心底層API由下面部分組成:

  • CRT(C runtime): 最底層的微軟對c、c++標準庫的實現版本;介面參照標準規範;MFC依賴於此。但是windows API不依賴於此,有內部自己的實現版本。
  • Windows API: 微軟的作業系統怎麼弄出來的,全靠它們了,以C的API形式提供。
  • MFC: 對windows API進行類的封裝。基本上涵蓋部分CRT和全部Windows API。該小組是AFX小組。
  • ATL: 微軟全面邁入組件解決方案時的封裝。該小組是Com小組。

如下表:

  

其實看看vc的目錄組織圖大概也知道其分組。

 MFC 靜態庫和動態庫

最流行的是使用MFC作為dll,同時將自身的也作為dll。在這種情況下,如果深挖進去,最容易發現的是MFC的dll。

參照 MSDN中的“Naming Conventions for MFC DLLs”,可以發現,基於動態連結程式庫的MFC的命名規範為:MFC[D|O|N]x[U][D].DLL。

主要包含的屬性為:功能模組(Core | OLE | DB | NET),版本(VC6對應42,VS2003對應70,VS2005對應80,VS2008對應90),是unicode還是Ansi,是release還是debug。

稍微注意的是:debug版本下每個功能模組對應一個lib;但是release版本下,合起來為一個統一的lib檔案MFC42.lib。

其實還存在,靜態連結庫。但是其名字可能更不著調 :[N|U]AFXDW[D].LIB

其中包含unicode和非unicode,debug和release區分。

 CRT 靜態庫和動態庫

參照MSDN中的“INFO: What Are the C/C++ Libraries My Program Would Link With?”。

當我們調用sprintf,wcslen等此類函數時,我們就依賴了該庫。

這個可以通過編譯設定:

實際上對應的編譯項是:/MD /ML /MT

3.靜態庫和動態庫核心

有關靜態庫和動態庫的相關概念,以及串連中出現的一些問題,其實所有的核心就是:

  • 搞清楚引用別人的庫是靜態還是動態庫;
  • 把自己作為庫給別人使用時是靜態庫還是動態庫

真正所謂取之與民,用之於民。

其中還經常出現的一個問題是,引用的系統底層庫有哪些,到底是靜態庫還是動態庫。通常,對於MFC程式,一定會依賴於MFC庫;可以選擇性的依賴CRT庫。搞清楚使用的靜態庫和動態庫,不要衝突就行。

幾種靜態庫和動態庫

在VC6中,對於靜態動態庫,去除組件作為一種特殊的動態庫外,還剩下5種類型。一一產生一個示範程式,研究設定,大概就可以看出區別。

靜態庫匯出的是 h標頭檔和lib檔案。該lib檔案包含著程式碼,會比較大。原始碼編譯的時候使用標頭檔,連結的時候使用lib檔案,運行時就不需要庫檔案了。

動態庫匯出的是 h標頭檔、lib和dll檔案。該lib檔案只包含著程式的函數索引位置,比較小。原始碼編譯時間使用標頭檔,連結時使用lib檔案,運行時需要dll檔案。

 

這是MFC dll

 以下是對各dll分析:

其實,本質上可以看出,只有兩種庫:靜態庫和動態庫;標明自身是靜態庫還是動態庫。

靜態庫由於生來是被別人使用的,所以也就不存在匯入匯出標識;

而動態庫一定要存在匯入匯出標識。對於dll,存在MFC dll和普通的win dll。其實所謂的MFC dll只不過是將DllMain進行特殊封裝,特別是為了方便資源的存取。而所謂的Extension dll,只不過是為了相容C;要求只匯出非MFC類的函數而已。

這些靜態庫如何使用MFC 庫,如何使用CRT庫,其實都是可以設定的。這點用來解決引用庫是什麼庫。

對於靜態庫和動態庫,MFC嚮導產生時,會自動弄出一些編譯設定項。但是最根本的核心還是dsp中的:

# TARGTYPE "Win32 (x86) Static Library" 0x0104

!MESSAGE "TestStaticLib - Win32 Release" (based on "Win32 (x86) Static Library")

!MESSAGE "TestStaticLib - Win32 Debug" (based on "Win32 (x86) Static Library")

如果要將一個靜態庫編譯成另一個動態庫,或者相反;只需要在dsp中統一尋找替換為另一種格式即可。當然,更加鼓勵的是產生多個編譯配置項。

避免衝突的方法

對於靜態庫和動態庫,在編譯連結中總是會存在問題。這些問題的根本原因在於:一個工程中,同時對於某一個工程,既引入了其靜態庫,又引入了其動態庫。這樣會出現同名衝突。

    解決的方法有兩種:

  • 確保所有工程對某個庫採用同一種方式引入。這個可能要搜遍所有工程
  • 對於編譯不過的工程,已知某一個庫衝突,將該庫的靜態和動態庫忽略一個即可。

 

4.如何最大化最合理利用各功能庫

  • 程式如果就是一個MFC程式,建議盡量使用MFC庫;盡量不依賴於CRT庫。
  • 程式如果只是一個WIN32 程式,建議盡量不使用MFC庫,選擇性的依賴於CRT庫。
  • 程式如果只是一個控制台程式,盡量依賴於CRT庫,少依賴於win api庫和MFC庫。

原則,盡量少的依賴庫。對於同功能的函數,可能CRT有,Win API庫,MFC庫,選擇性的找到正確的庫。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.