欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
MFC DLL向導(摘) - 醬壇子 - C++博客
雖然能用DLL實(shí)現的東西都可以用COM來(lái)實(shí)現,但DLL的優(yōu)點(diǎn)確實(shí)不少,它更容易創(chuàng )建。本文將討論如何利用MFC來(lái)創(chuàng )建不同類(lèi)型的DLL,以及如何使用他們。

一、DLL的不同類(lèi)型
    使用MFC可以生成兩種類(lèi)型的DLL:MFC擴展DLL和常規DLL。常規DLL有可以分為動(dòng)態(tài)連接和靜態(tài)連接。Visual C++還可以生成WIN32 DLL,但不是這里討論的主要對象。
1、MFC擴展DLL
   每個(gè)DLL都有某種類(lèi)型的接口:變量、指針、函數、客戶(hù)程序訪(fǎng)問(wèn)的類(lèi)。它們的作用是讓客戶(hù)程序使用DLL,MFC擴展DLL可以有C++的接口。也就是它可以導出C++類(lèi)給客戶(hù)端。導出的函數可以使用C++/MFC數據類(lèi)型做參數或返回值,導出一個(gè)類(lèi)時(shí)客戶(hù)端能創(chuàng )建類(lèi)對象或者派生這個(gè)類(lèi)。同時(shí),在DLL中也可以使用DLL和MFC。
   Visual C++使用的MFC類(lèi)庫也是保存在一個(gè)DLL中,MFC擴展DLL動(dòng)態(tài)連接到MFC代碼庫的DLL,客戶(hù)程序也必須要動(dòng)態(tài)連接到MFC代碼庫的DLL。(這里談到的兩個(gè)DLL,一個(gè)是我們自己編寫(xiě)的DLL,一個(gè)裝MFC類(lèi)庫的DLL)現在MFC代碼庫的DLL也存在多個(gè)版本,客戶(hù)程序和擴展DLL都必須使用相同版本的MFC代碼DLL。所以為了讓MFC擴展DLL能很好的工作,擴展DLL和客戶(hù)程序都必須動(dòng)態(tài)連接到MFC代碼庫DLL。而這個(gè)DLL必須在客戶(hù)程序運行的計算機上。
2、常規DLL
   使用MFC擴展DLL的一個(gè)問(wèn)題就是DLL僅能和MFC客戶(hù)程序一起工作,如果需要一個(gè)使用更廣泛的DLL,最好采用常規DLL,因為它不受MFC的某些限制。常規DLL也有缺點(diǎn):它不能和客戶(hù)程序發(fā)送指針或MFC派生類(lèi)和對象的引用。一句話(huà)就是常規DLL和客戶(hù)程序的接口不能使用MFC,但在DLL和客戶(hù)程序的內部還是可以使用MFC。
   當在常規DLL的內部使用MFC代碼庫的DLL時(shí),可以是動(dòng)態(tài)連接/靜態(tài)連接。如果是動(dòng)態(tài)連接,也就是常規DLL需要的MFC代碼沒(méi)有構建到DLL中,這種情況有點(diǎn)和擴展DLL類(lèi)似,在DLL運行的計算機上必須要MFC代碼庫的DLL。如果是靜態(tài)連接,常規DLL里面已經(jīng)包含了需要的MFC代碼,這樣DLL的體積將比較大,但它可以在沒(méi)有MFC代碼庫DLL的計算機上正常運行。

二、建立DLL
    利用Visual C++提供的向導功能可以很容易建立一個(gè)不完成任何實(shí)質(zhì)任務(wù)的DLL,這里就不多講了,主要的任務(wù)是如何給DLL添加功能,以及在客戶(hù)程序中利用這個(gè)DLL
1、導出類(lèi)
   用向導建立好框架后,就可以添加需要導出類(lèi)的.cpp .h文件到DLL中來(lái),或者用向導創(chuàng )建C++ Herder File/C++ Source File。為了能導出這個(gè)類(lèi),在類(lèi)聲明的時(shí)候要加“_declspec(dllexport)”,如:
class _declspec(dllexport) CMyClass
{
     ...//聲明
}
如果創(chuàng )建的MFC擴展DLL,可以使用宏:AFX_EXT_CLASS:
class AFX_EXT_CLASS CMyClass
{
     ...//聲明
}
這樣導出類(lèi)的方法是最簡(jiǎn)單的,也可以采用.def文件導出,這里暫不詳談。
2、導出變量、常量、對象
   很多時(shí)候不需要導出一個(gè)類(lèi),可以讓DLL導出一個(gè)變量、常量、對象,導出它們只需要進(jìn)行簡(jiǎn)單的聲明:_declspec(dllexport) int MyInt;
  _declspec(dllexport) extern const COLORREF MyColor=RGB(0,0,0);
  _declspec(dllexport) CRect rect(10,10,20,20);
要導出一個(gè)常量時(shí)必須使用關(guān)鍵字extern,否則會(huì )發(fā)生連接錯誤。
注意:如果客戶(hù)程序識別這個(gè)類(lèi)而且有自己的頭文件,則只能導出一個(gè)類(lèi)對象。如果在DLL中創(chuàng )建一個(gè)類(lèi),客戶(hù)程序不使用頭文件就無(wú)法識別這個(gè)類(lèi)。
  當導出一個(gè)對象或者變量時(shí),載入DLL的每個(gè)客戶(hù)程序都有一個(gè)自己的拷貝。也就是如果兩個(gè)程序使用的是同一個(gè)DLL,一個(gè)應用程序所做的修改不會(huì )影響另一個(gè)應用程序。
  我們在導出的時(shí)候只能導出DLL中的全局變量或對象,而不能導出局部的變量和對象,因為它們過(guò)了作用域也就不存在了,那樣DLL就不能正常工作。如:
MyFunction()
{
      _declspec(dllexport) int MyInt;
      _declspec(dllexport) CMyClass object;
}
3、導出函數
導出函數和導出變量/對象類(lèi)似,只要把_declspec(dllexport)加到函數原型開(kāi)始的位置:
_declspec(dllexport) int MyFunction(int);
如果是常規DLL,它將和C寫(xiě)的程序使用,聲明方式如下:
extern "c" _declspec(dllexport) int MyFunction(int);
實(shí)現:
extern "c" _declspec(dllexport) int MyFunction(int x)
{
     ...//操作
}
如果創(chuàng )建的是動(dòng)態(tài)連接到MFC代碼庫DLL的常規DLL,則必須插入AFX_MANAGE_STATE作為導出函數的首行,因此定義如下:
extern "c" _declspec(dllexport) int MyFunction(int x)
{
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     ...//操作
}
有時(shí)候為了安全起見(jiàn),在每個(gè)常規DLL里都加上,也不會(huì )有任何問(wèn)題,只是在靜態(tài)連接的時(shí)候這個(gè)宏無(wú)效而已。這是導出函數的方法,記住只有MFC擴展DLL才能讓參數和返回值使用MFC的數據類(lèi)型。
4、導出指針
導出指針的方式如下:
_declspec(dllexport) int *pint;
_declspec(dllexport) CMyClass object = new CMyClass;
如果聲明的時(shí)候同時(shí)初始化了指針,就需要找到合適的地方類(lèi)釋放指針。在擴展DLL中有個(gè)函數DllMain()。(注意函數名中的兩個(gè)l要是小寫(xiě)字母),可以在這個(gè)函數中處理指針:
# include "MyClass.h"
_declspec(dllexport) CMyClass *pobject = new CMyClass;
DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
{
    if(dwReason == DLL_PROCESS_ATTACH)
    {
        .....//
    }
    else if(dwReason == DLL_PROCESS_DETACH)
    {
        delete pobject;
    }
}
常規DLL有一個(gè)從CWinApp派生的類(lèi)對象處理DLL的開(kāi)和關(guān),可以使用類(lèi)向導添加InitInstance/ExitInstance函數。
int CMyDllApp::ExitInstance()
{
    delete pobject;
    return CWinApp::ExitInstance();
}

三、在客戶(hù)程序中使用DLL
    編譯一個(gè)DLL時(shí)將創(chuàng )建兩個(gè)文件.dll文件和.lib文件。首先將這兩個(gè)文件復制到客戶(hù)程序項目的文件夾里,這里需要注意DLL和客戶(hù)程序的版本問(wèn)題,盡量使用相同的版本,都使用RELEASE或者都是DEBUG版本。
   接著(zhù)就需要在客戶(hù)程序中設置LIB文件,打開(kāi)Project Settings--->Link--->Object/library Modules中輸入LIB的文件名和路徑。如:Debug/SampleDll.lib。除了DLL和LIB文件外,客戶(hù)程序需要針對導出類(lèi)、函數、對象和變量的頭文件,現在進(jìn)行導入添加的關(guān)鍵字就是:_declspec(dllimport),如:
_declspec(dllimport) int MyFunction(int);
_declspec(dllimport) int MyInt;
_declspec(dllimport) CMyClass object;
extern "C" _declspec(dllimport) int MyFunction(int);
在有的時(shí)候為了導入類(lèi),要把相應類(lèi)的頭文件添加到客戶(hù)程序中,不同的是要修改類(lèi)聲明的標志:
class _declspec(dllimport) CMyClass,如果創(chuàng )建的是擴展DLL,兩個(gè)位置都是:
class AFX_EXT_CLASS CMyClass。


使用DLL的一個(gè)比較嚴重的問(wèn)題就是編譯器之間的兼容性問(wèn)題。不同的編譯器對c++函數在二進(jìn)制級別的實(shí)現方式是不同的。所以對基于C++的DLL,如果編譯器不同就有很麻煩的。如果創(chuàng )建的是MFC擴展DLL,就不會(huì )存在問(wèn)題,因為它只能被動(dòng)態(tài)連接到MFC的客戶(hù)應用程序。這里不是本文討論的重點(diǎn)。

一、重新編譯問(wèn)題
我們先來(lái)看一個(gè)在實(shí)際中可能遇到的問(wèn)題:
    比如現在建立好了一個(gè)DLL導出了CMyClass類(lèi),客戶(hù)也能正常使用這個(gè)DLL,假設CMyClass對象的大小為30字節。如果我們需要修改DLL中的CMyClass類(lèi),讓它有相同的函數和成員變量,但是給增加了一個(gè)私有的成員變量int類(lèi)型,現在CMyClass對象的大小就是34字節了。當直接把這個(gè)新的DLL給客戶(hù)使用替換掉原來(lái)30字節大小的DLL,客戶(hù)應用程序期望的是30字節大小的對象,而現在卻變成了一個(gè)34字節大小的對象,糟糕,客戶(hù)程序出錯了。
    類(lèi)似的問(wèn)題,如果不是導出CMyClass類(lèi),而在導出的函數中使用了CMyClass,改變對象的大小仍然會(huì )有問(wèn)題的。這個(gè)時(shí)候修改這個(gè)問(wèn)題的唯一辦法就是替換客戶(hù)程序中的CMyClass的頭文件,全部重新編譯整個(gè)應用程序,讓客戶(hù)程序使用大小為34字節的對象。
    這就是一個(gè)嚴重的問(wèn)題,有的時(shí)候如果沒(méi)有客戶(hù)程序的源代碼,那么我們就不能使用這個(gè)新的DLL了。

二、解決方法  
 為了能避免重新編譯客戶(hù)程序,這里介紹兩個(gè)方法:(1)使用接口類(lèi)。(2)使用創(chuàng )建和銷(xiāo)毀類(lèi)的靜態(tài)函數。
1、使用接口類(lèi)
   接口類(lèi)的也就是創(chuàng )建第二個(gè)類(lèi),它作為要導出類(lèi)的接口,所以在導出類(lèi)改變時(shí),也不需要重新編譯客戶(hù)程序,因為接口類(lèi)沒(méi)有發(fā)生變化。
   假設導出的CMyClass類(lèi)有兩個(gè)函數FunctionA FunctionB?,F在創(chuàng )建一個(gè)接口類(lèi)CMyInte***ce,下面就是在DLL中的CMyInte***ce類(lèi)的頭文件的代碼:
# include "MyClass.h"
class _declspec(dllexport) CMyInte***ce
{
     CMyClass *pmyclass;
     CMyInte***ce();
     ~CMyInte***ce();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
而在客戶(hù)程序中的頭文件稍不同,不需要INCLUDE語(yǔ)句,因為客戶(hù)程序沒(méi)有它的拷貝。相反,使用一個(gè)CMyClass的向前聲明,即使沒(méi)有頭文件也能編譯:
class _declspec(dllexport) CMyInte***ce
{
     class CMyClass;//向前聲明
     CMyClass *pmyclass;
     CMyInte***ce();
     ~CMyInte***ce();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
在DLL中的CMyInte***ce的實(shí)現如下:
CMyInte***ce::CMyInte***ce()
{
      pmyclass = new CMyClass();
}
CMyInte***ce::~CMyInte***ce()
{
     delete pmyclass;
}
int CMyInte***ce::FunctionA()
{
     return pmyclass->FunctionA();
}
int CMyInte***ce::FunctionB()
{
     return pmyclass->FunctionB();   
}
.....
對導出類(lèi)CMyClass的每個(gè)成員函數,CMyInte***ce類(lèi)都提供自己的對應的函數??蛻?hù)程序與CMyClass沒(méi)有聯(lián)系,這樣任意改CMyClass也不會(huì )有問(wèn)題,因為CMyInte***ce類(lèi)的大小沒(méi)有發(fā)生變化。即使為了能訪(fǎng)問(wèn)CMyClass中的新增變量而給CMyInte***ce類(lèi)加了函數也不會(huì )有問(wèn)題的。
   但是這種方法也存在明顯的問(wèn)題,對導出類(lèi)的每個(gè)函數和成員變量都要對應實(shí)現,有的時(shí)候這個(gè)接口類(lèi)會(huì )很龐大。同時(shí)增加了客戶(hù)程序調用所需要的時(shí)間。增加了程序的開(kāi)銷(xiāo)。

2、使用靜態(tài)函數
   還可以使用靜態(tài)函數來(lái)創(chuàng )建和銷(xiāo)毀類(lèi)對象。創(chuàng )建一個(gè)導出類(lèi)的時(shí)候,增加兩個(gè)靜態(tài)的公有函數CreateMe()/DestroyMe(),頭文件如下:
class _declspec(dllexport) CMyClass
{
     CMyClass();
     ~CMyClass();
  public:
     static CMyClass *CreateMe();
     static void DestroyMe(CMyClass *ptr);
};
實(shí)現函數就是:
CMyClass * CMyClass::CMyClass()
{
      return new CMyClass;
}
void CMyClass::DestroyMe(CMyClass *ptr)
{
      delete ptr;
}
然后象其他類(lèi)一樣導出CMyClass類(lèi),這個(gè)時(shí)候在客戶(hù)程序中使用這個(gè)類(lèi)的方法稍有不同了。如若想創(chuàng )建一個(gè)CMyClass對象,就應該是:
CMyClass x;
CMyClass *ptr = CMyClass::CreateMe();
在使用完后刪除:
CMyClass::DestroyMe(ptr);
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
MFC DLL向導(二)(使用接口類(lèi),使用創(chuàng )建和銷(xiāo)毀類(lèi)的靜態(tài)函數)
喜訊:由*.dll文件得出*.lib文件的方法已經(jīng)找到__問(wèn)吧_所有相關(guān)_中國學(xué)網(wǎng)
VC 動(dòng)態(tài)鏈接庫(DLL)編程深入淺出
如何編寫(xiě)DLL文件(開(kāi)發(fā)環(huán)境VS2005)
DLL(Dynamic Link Libraries)
vc dll編程
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久