青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

醬壇子

專注C++技術 在這里寫下自己的學習心得 感悟 和大家討論 共同進步(歡迎批評!!!)

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  66 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

公告

王一偉 湖南商學院畢業 電子信息工程專業

常用鏈接

留言簿(19)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 389620
  • 排名 - 64

最新隨筆

最新評論

閱讀排行榜

評論排行榜

雖然能用DLL實現的東西都可以用COM來實現,但DLL的優點確實不少,它更容易創建。本文將討論如何利用MFC來創建不同類型的DLL,以及如何使用他們。

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

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

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


使用DLL的一個比較嚴重的問題就是編譯器之間的兼容性問題。不同的編譯器對c++函數在二進制級別的實現方式是不同的。所以對基于C++的DLL,如果編譯器不同就有很麻煩的。如果創建的是MFC擴展DLL,就不會存在問題,因為它只能被動態連接到MFC的客戶應用程序。這里不是本文討論的重點。

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

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

2、使用靜態函數
?? 還可以使用靜態函數來創建和銷毀類對象。創建一個導出類的時候,增加兩個靜態的公有函數CreateMe()/DestroyMe(),頭文件如下:
class _declspec(dllexport) CMyClass
{
???? CMyClass();
???? ~CMyClass();
? public:
???? static CMyClass *CreateMe();
???? static void DestroyMe(CMyClass *ptr);
};
實現函數就是:
CMyClass * CMyClass::CMyClass()
{
????? return new CMyClass;
}
void CMyClass::DestroyMe(CMyClass *ptr)
{
????? delete ptr;
}
然后象其他類一樣導出CMyClass類,這個時候在客戶程序中使用這個類的方法稍有不同了。如若想創建一個CMyClass對象,就應該是:
CMyClass x;
CMyClass *ptr = CMyClass::CreateMe();
在使用完后刪除:
CMyClass::DestroyMe(ptr);
posted on 2006-10-16 08:42 @王一偉 閱讀(888) 評論(0)  編輯 收藏 引用 所屬分類: 1. MFC
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99视频一区| 久久精品视频在线免费观看| 国产亚洲精品一区二区| 欧美日韩视频不卡| 国产视频精品va久久久久久| 亚洲女人天堂成人av在线| 亚洲精品一区二区三区av| 欧美精品在线观看91| 亚洲福利视频网站| 欧美ed2k| 欧美不卡福利| 亚洲一区视频在线观看视频| 久久国产精品毛片| 欧美一区亚洲二区| 久久久久久久91| 在线视频欧美日韩| 亚洲免费影视第一页| 国产一区二区三区自拍| 亚洲精品三级| 国产欧美日韩亚洲一区二区三区| 欧美中文在线观看国产| 免费一级欧美在线大片| 亚洲裸体视频| 亚洲国产一区二区三区a毛片| 美女尤物久久精品| 久久综合久色欧美综合狠狠 | 欧美激情一区二区三区蜜桃视频| 欧美国产免费| 久久久999精品视频| 欧美精品在线一区| 欧美国产成人精品| 狠狠色狠狠色综合日日91app| 99精品99久久久久久宅男| 亚洲国产成人精品女人久久久| 亚洲国产精品ⅴa在线观看| 亚洲视频免费| 亚洲欧美精品suv| 欧美精品偷拍| 亚洲第一二三四五区| 欧美日本韩国在线| 亚洲欧洲一区二区天堂久久| 亚洲激情网址| 欧美精品日韩综合在线| 最新高清无码专区| 9色国产精品| 国产精品老牛| 久久都是精品| 欧美岛国激情| 亚洲精品日韩激情在线电影| 免费视频久久| 在线亚洲美日韩| 久久不见久久见免费视频1| 国产精品腿扒开做爽爽爽挤奶网站| 亚洲午夜精品在线| 久久精品国产欧美亚洲人人爽| 国产欧美亚洲视频| 麻豆freexxxx性91精品| 欧美国产日韩一区二区在线观看| 亚洲第一天堂av| 国产精品h在线观看| 久久精品国产综合| 亚洲国产一区二区精品专区| 亚洲淫片在线视频| 1024国产精品| 欧美日韩国产在线一区| 亚洲一级一区| 亚洲日本精品国产第一区| 久久理论片午夜琪琪电影网| 亚洲免费电影在线观看| 国产午夜亚洲精品理论片色戒| 久久精品亚洲一区二区三区浴池| 亚洲精品小视频在线观看| 美日韩精品视频免费看| 欧美大片一区| 久久久久五月天| 欧美亚洲三级| 午夜精品在线观看| 亚洲砖区区免费| 亚洲免费视频在线观看| 亚洲一区二区毛片| 91久久久一线二线三线品牌| 久久中文久久字幕| 玖玖玖国产精品| 久久久久久久国产| 久久综合久久美利坚合众国| 一本色道久久综合精品竹菊| 免费一级欧美片在线观看| 久久久久久久久久久一区| 久久亚洲高清| 久久亚洲综合色| 另类激情亚洲| 欧美国产精品日韩| 亚洲欧洲三级电影| 日韩一级精品视频在线观看| 亚洲精品久久久久久久久久久久久| 欧美激情欧美激情在线五月| 亚洲国产日韩欧美在线图片| 亚洲精品视频在线观看网站| 亚洲精品国产欧美| 亚洲欧美在线一区二区| 狼人社综合社区| 国产精品看片资源| 亚洲国产日韩一区| 亚洲一区二区三区激情| 欧美一区二区精品| 欧美成人午夜| 亚洲欧美日韩一区在线观看| 欧美+亚洲+精品+三区| 国产精品腿扒开做爽爽爽挤奶网站| 国产一区二区日韩精品欧美精品| 亚洲国产天堂久久综合网| 欧美一区二区三区免费观看视频| 欧美成人资源| 久久亚洲午夜电影| 亚洲一区二区三区精品动漫| 久久久噜噜噜久噜久久| 欧美日韩综合网| 亚洲伦理中文字幕| 亚洲成色www久久网站| 欧美怡红院视频| 国产欧美日韩亚洲| 久久精品国产99精品国产亚洲性色 | 国产欧美精品一区| 亚洲小视频在线观看| 91久久综合亚洲鲁鲁五月天| 欧美高清在线观看| 亚洲天堂成人在线视频| 亚洲精品欧美激情| 欧美精品不卡| 亚洲视频你懂的| 亚洲午夜久久久| 国产一二精品视频| 欧美freesex交免费视频| 免费欧美电影| 亚洲视频在线免费观看| 亚洲第一网站| 国产一区二区三区在线播放免费观看| 激情五月***国产精品| 亚洲天堂视频在线观看| 一区二区三区日韩欧美精品| 欧美高清不卡| 亚洲欧洲av一区二区| 亚洲天堂av综合网| 在线视频成人| 亚洲一区三区视频在线观看| 伊甸园精品99久久久久久| 亚洲缚视频在线观看| 欧美日韩三区四区| 欧美国产先锋| 国产精品一区亚洲| 欧美.日韩.国产.一区.二区| 欧美日韩一区二区欧美激情| 欧美一区二区国产| 欧美色欧美亚洲另类二区| 久久视频免费观看| 欧美性猛交xxxx免费看久久久| 国产日产亚洲精品| 最新国产乱人伦偷精品免费网站| 国产精品伦一区| 99精品久久久| 亚洲美女精品久久| 老色批av在线精品| 久久综合九色九九| 国产亚洲毛片在线| 一区二区三区四区精品| 亚洲黄网站黄| 久久一区二区三区四区| 久久精品综合一区| 国产日韩欧美制服另类| 亚洲制服少妇| 亚洲欧美日韩视频一区| 国产精品区免费视频| 亚洲一区中文| 欧美亚洲综合在线| 欧美新色视频| 欧美在线短视频| 久久久久久久久久久一区| 国产婷婷97碰碰久久人人蜜臀| 亚洲免费观看视频| 久久国产精品久久国产精品| 国产一区二区三区成人欧美日韩在线观看 | 欧美日韩在线综合| 亚洲影院一区| 欧美/亚洲一区| 亚洲欧美日韩另类| 亚洲精品免费一二三区| 国产精品vvv| 久久亚裔精品欧美| 亚洲精品在线一区二区| 欧美在线短视频| 一本一本a久久| 亚洲国产成人久久综合一区| 国产精品尤物福利片在线观看| 久久裸体视频| 亚洲私人影吧| 99精品国产热久久91蜜凸| 欧美黄色一区| 欧美www视频| 亚洲国产影院| 国产精品高精视频免费|