MFC DLL指南(一)--進化論

這裏要提到的一點是,在用COM和ATL前,程序員一般用.DLLs來代替它們. 你可以用.DLL做很多事.如果你有幾個程序要用到相同的函數或資源,你可以將代碼放到一個.DLL中.將多個程序要共同用到的代碼放到一個簡單的.DLL中可以節省維護時間,因爲代碼就在一個地方.:)修理和其他的改動最多做一次就夠了.如果你有一個在不同時間用不同程序的程序,你應該把這些程序做成.DLLs,根據需要的導入相應的.DLL.有很多理由要用到.DLLS.
  雖然用.DLL能做的COM全能做,但是仍有很多好原因使得我們要用.DLLs,所以它們沒有消失.但是.DLLs還是有很多嚴重缺點的,這些嚴重的缺點就是我們爲什麼會首先想到用COM.但.DLLs仍然是很實用的工具.對照COM和ATL,.DLLs是非常簡單的來實現的.學習COM和ATL需要投入大量的時間和努力.實現.DLL卻相對簡單,修改起來也不難.如果你會一些C++和MFC,你現在就可以實現.DLLs.
  這篇文章回顧一下用MFC實現.DLLs的幾種形式,包括何時用和怎麼用各種形式.在下一篇將討論.DLLs的侷限性(這就是爲何會出現COM和ATL)

  
Different types of .DLLs

  可以用MFC來實現兩種.DLLs:一個是MFC擴展.DLL,一個是正規的.DLLs.正規的.DLLs有兩種實現方式:dynamically linked 或者 statically linked.Visual C++也允許你用generic Win32 .DLL,但本文我們只討論以MFC爲基礎的.DLL形式.

  MFC extension .DLLs
  每一個.DLL都有一些接口.接口是一套變量,指針,函數或者是類,可以通過客戶程序來訪問.MFC的擴展.DLL有一個C++形式的接口,也就是說它提供給客戶程序("export")C++函數或者整個類.導出函數可以用C++或者MFC的數據形式作爲參數或返回值.當導出整個類,客戶程序可以創建此類的對象或者派生於此類.在.DLL中,你也可以用MFC和C++.
  Visual C++用的MFC的類代碼庫也存在於.DLL中.一個擴展.DLL是動態連接到MFC的代碼庫的.DLL的.客戶程序也必須動態的連接到MFC的代碼庫.隨着時間的推移,MFC的庫也在增長.結果,就有了幾個不同的MFC的代碼庫的版本.客戶端和擴展的.DLL必須建立在相同版本的MFC上.因此,一個MFC擴展的.DLL要運行,客戶端和此擴展的.DLL必須動態的連到相同的MFC代碼庫的.DLL上,並且,此庫還得在該程序運行的機器上好使.
  注意:如果你的程序靜態的連接到MFC,但是你希望改變它便於從一個擴展的.DLL中訪問函數,這時,你要改此應用程序爲動態連接到MFC.在Visual C++,在菜單中選"Project | Settings",在"General"設置標籤中可以把你的程序改成動態連接到MFC.
  MFC擴展.DLLs非常小.你可以建立一個導出一些函數或者類的大約10-15KB的.DLL.顯然的,你的.DLL的大小要以你要存多少代碼到你的.DLL中爲準.但是通常MFC擴展的.DLLs是相對小和快捷的.
  
  Regular .DLLs
  MFC的擴展.DLL只能工作在用MFC編的客戶程序上.如果你的.DLL可以被大多數的Win32程序導入和運行,你應改選擇正規的.DLL.但你只能導出C-style函數.你不能導出類.你不能導出C++函數或overloaded函數.不能用MFC的數據類型作爲參數和返回值.但可以在你的.DLL中用C++和MFC,但是你的接口必須全是C-style.  
  當然正規的.DLL也要訪問MFC的代碼庫的.DLL.可以動態,可以靜態連接.如果動態連接,意味着你的.DLL函數所需的MFC代碼不用建立在你的.DLL中,你的.DLL會從你的客戶端的機器上MFC的代碼庫的.DLL中取得所需要的代碼.如果正確的MFC代碼庫的.DLL版本沒找到,你的.DLL將不能工作.像MFC擴展的.DLL一樣,正規的.DLL也非常小,只能在客戶端所在的機器有MFC代碼庫的.DLL情況下工作.
  如果你靜態連接到MFC代碼庫,你的.DLL包括它自己的所有的所需的MFC代碼.那麼,它將非常龐大,但是它不依賴於客戶端的電腦配置.如果你不知道主機的機器配置情況,這是一個很好的方法.如果你的客戶在你的公司範圍內,你可以知道他們的MFC .DLL的配置情況,或者你的安裝程序帶了正確版本的MFC .DLL,那麼靜態連接就不是一個好方法了.

  
Building a .DLL

  可以用App Wizard來實現以MFC爲基礎的.DLL.選擇"File | New",在"Projects"標籤上,選擇"MFC AppWizard (.DLL).",爲你的工程選一個名字,然後單擊"OK".在下一個屏幕,選擇建立一個MFC擴展的.DLL,或者正規的.DLL"using shared MFC .DLL"(就是動態連接到MFC),或者正規的.DLL(靜態的連接到MFC).選擇其中一個,按"Finish".
  App Wizard新建立的.DLL沒做任何事.編譯新的.DLL,但是它不導出任何類和函數,本質上來說,沒有任何用,你現在有兩個工作:
  1.增加函數.
  2.修改客戶端來調用你的.DLL.
  
  Export a Class
  上面提到,只有MFC的擴展.DLL能導出MFC/C++類.假設你建立了一個擴展的.DLL,你可以通過從另一個工程加入.cpp和.h文件來創建一個類,也可以在你的工程中創建新類.要導出這個新類,你必須在類的聲明前加一個宏"AFX_EXT_CLASS",像這樣:

     class AFX_EXT_CLASS CMyClass
     {
          //class declaration goes here
     };
  
  還用一種方法來導出一個類,很簡單而且很好,我會在下面討論客戶端如何做才能用上你的導出類提到.
  
  Export objects and variables
  代替導出整個類的方法,你可以導出該類在.DLL中的對象.客戶端程序可以調用所有的該導出對象的公有函數和訪問它的公有成員變量.
  首先,創建一個.h文件,定義了你的新類.然後創建實現你的新類的.cpp文件.在.cpp文件底部,在你所有的公有的,私有的類函數後,創建一個這樣的類的實例:

     _declspec(dllexport) CMyClass myObject;

  這行的作用是創建一個CMyClass類的實例,當客戶端導入.DLL時,使得客戶端可以訪問該實例.通過該實例,訪問它的公有函數和成員編量.注意,每個客戶端導入.DLL將獲得該實例的一個拷貝,也就是說,如果不同的程序訪問相同的.DLL,如果一個程序改變了該實例,不會影響另一個程序.
  除了導出實例,你可以用同樣的方法導出變量.如果你加上此行:
  
     _declspec(dllexport) int x;

  就可以導出變量,爲客戶端應用.下面說的很重要:你只能導出全局的實例或者變量.局部的實例或者變量當它們跑出作用域,就會停止生存.如果用下面的方法,將不會正常工作:

     MyFunction( )
     {
          _declspec(dllexport) CMyClass myObject;
          _declspec(dllexport) int x;
     }

  一旦實例或者變量跑出作用域,它們將停止生存.

  Export a function
  導出函數和導出變量是很相似的.你可以簡單的在函數前面加上"_declspec(dllexport)"

     _declspec(dllexport) int MyExportedFunction(int);

  這就是導出的全部.記住,只有MFC擴展的.DLL能導出C++函數或者以MFC的數據類型爲參數或者返回值.正規的.DLLs只能導出C-style函數.

  
Using the .DLL in a client application

  一個.DLL不能運行它自己.它需要客戶端導入它,調用它的接口.
  當你編譯你的.DLL時,編譯器創建兩個很重要的文件: .DLL文件和.lib文件.你的客戶端需要這兩個文件.你必須拷貝它們到客戶端的工程文件夾.

  除了.DLL和.lib文件,你的客戶端還需要要導出的類,函數,實例和變量所在的頭文件.要導出函數時要加"_declspec(dllexport)"聲明.現在要導入了,就要加入"_declspec(dllimport)"聲明.如下:

     _declspec(dllimport) CMyClass myObject;
     _declspec(dllimport) int x;
     _declspec(dllimport) int MyExportedFunction(int);

  爲了可讀性,我們可以這樣寫:

     #define DLLIMPORT _declspec(dllimport)
     
     DLLIMPORT CMyClass myObject;
     DLLIMPORT int x;
     DLLIMPORT int MyExportedFunction(int);

  現在你聲明瞭你的實例,變量和函數,可以用了.:)
  要導出整個類,你必須將整個.h頭文件拷過來..DLL和客戶端要有唯一的關於此導出類的頭文件.記住,類的聲明要加上: AFX_EXT_CLASS 宏.
  一旦你建立了客戶端,你已經準備給客戶用了,你應該給他們你的Release可執行文件和Release的.DLL.不用給用戶.lib文件..DLL可以放在客戶程序的目錄,或者系統目錄.還有上面提到的,你要提供正確的MFC代碼庫的.DLL.這個.DLL是你的機器裝Visual C++時候用的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章