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

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

dll的概念、dll導出類(轉)

dll的概念、dll導出類(轉)

Posted on 2011-07-22 14:59 白耘 閱讀(875) 評論(0) 編輯 收藏 來源:http://www.cnblogs.com/whiteyun/archive/2011/07/22/2113668.html

1、 DLL的概念

DLL(Dynamic Linkable Library),動態鏈接庫,可以向程序提供一些函數、變量或類。這些可以直接拿來使用。

靜態鏈接庫與動態鏈接庫的區別:

 

(1)靜態鏈接庫與動態鏈接庫都是共享代碼的方式。靜態鏈接庫把最后的指令都包含在最終生成的EXE文件中了;動態鏈接庫不必被包含在最終EXE文件中,EXE文件執行時可以“動態”地引用和卸載這個與EXE獨立的DLL文件。

 

(2)靜態鏈接庫中不能再包含其他的動態鏈接庫或者靜態庫,而在動態鏈接庫中還可以再包含其他的動態或靜態鏈接庫。

 

動態鏈接庫的分類:Visual C++支持三種DLL,它們分別是:

(1)Non-MFC DLL(非MFC動態庫)

非MFC動態庫不采用MFC類庫結構,其導出函數為標準的C接口,能被非MFC或MFC編寫的應用程序所調用;

 

(2)MFC Regular DLL(MFC規則DLL)

MFC規則DLL 包含一個繼承自CWinApp的類,但其無消息循環;

 

(3)MFC Extension DLL(MFC擴展DLL):MFC擴展DLL采用MFC的動態鏈接版本創建,它只能被用MFC類庫所編寫的應用程序所調用。

 

2、 創建一個DLL

 

2.1 非MFC的DLL

 

2.1.1聲明導出函數:

 

extern “C” __declspec(dllexport) int add(int a, int b);

 

其中 extern “C”為聲明為C編譯。由于C++編譯器在編譯的時候會造成其函數名的該變,在其他應用程序中導致函數不可調用,而C編譯器則不會在編譯后改變其函數名。這樣如果用C編譯的程序來調用該dll中的函數時,可能會造成找不到該函數。

 

__declspec(dllexport)表示該函數為DLL輸出函數,即其他應用程序可以調用該函數

 

從dll中聲明輸出函數有兩種方式:
(1) 用模塊定義(.def) 文件聲明,.def文件為鏈接器提供了有關被鏈接程序的導出、屬性及其他方面的信息。
(2) 用__declspec(dllexport)來聲明函數

 

如果使用Visual C++來創建dll,對于同樣用VC創建的exe來說,調用dll沒有什么問題。

而如果用其他工具來創建的exe來調用dll,就會出現問題。因為即使你不用C++編譯器,Microsoft C編譯器也會損害C函數。

當用__stdcall將函數輸出時,C編譯器會將函數改為_func@1的形式。在這里需要在.def文件中加入EXPORTS節來輸出函數:

 

EXPORTS
func
這樣,dll將用func函數名來輸出函數。

 

另一種方式是用#pragma (linker, “/exports:func=_func@1”),告訴編譯器輸出函數func,這種方式沒有前一種好。

 

如果通過VC++編寫的DLL欲被其他語言編寫的程序調用應將函數的調用方式聲明為__stdcall方式。

WINAPI都采用這種方式,而C/C++ 缺省的調用方式卻為__cdecl。__stdcall方式與__cdecl對函數名最終生成符號的方式不同。

若采用C編譯方式(在C++中需將函數聲明為extern "C"),__stdcall調用約定在輸出函數名前面加下劃線,后面加“@”符號和參數的字節數,

形如_functionname@number;而__cdecl調用約定僅在輸出函數名前面加下劃線,形如_functionname。

 

lib.def : 導出DLL函數
LIBRARY dllTest
EXPORTS
add @ 1
.def文件的規則為:
   (1)LIBRARY語句說明.def文件相應的DLL;
   (2)EXPORTS語句后列出要導出函數的名稱。可以在.def文件中的導出函數名后加@n,表示要導出函數的序號為n

(在進行函數調用時,這個序號將發揮其作用);

   (3).def 文件中的注釋由每個注釋行開始處的分號 (;) 指定,且注釋不能與語句共享一行。
   由此可以看出,例子中lib.def文件的含義為生成名為“dllTest”的動態鏈接庫,導出其中的add函數,并指定add函數的序號為1。

 

2.1.2 Dll的調用方式: 

 

DLL的調用分為兩種方式:動態和靜態顯示動態鏈接隱式動態鏈接)

 

(1) 動態調用(顯示動態鏈接):

typedef int(*lpAddFun)(int, int); //宏定義函數指針類型

lpAddFun add;//函數指針
HINSTANCE hDll=LoadLibrary(“path”);
add=(lpAddFun)GetProcAddress(hDll, "add");//獲得dll中的add函數指針
FreeLibrary(hDll);

 

在從dll調用中返回的函數、指針或者類都是以指針的方式的,即返回的是函數、變量或類的地址。這里一定要注意,不能簡單的用函數名來賦值。

 

(2) 靜態調用(隱式動態鏈接):

將生成的.dll和.lib文件拷入到調用dll的工程中,用命令

#pragma comment(lib,"dllTest.lib"),實現靜態調用,即把該dll在編譯的時候也編譯到exe文件中去,而后在工程中調用時用下面的代碼:

 

#pragma comment(lib,"dllTest.lib")//.lib文件中僅僅是關于其對應DLL文件中函數的重定位信息
extern "C" __declspec(dllimport) add(int x,int y);
int main(int argc, char* argv[])
{
int result = add(2,3);
printf("%d",result);
return 0;
}

 

   由上述代碼可以看出,靜態調用方式的順利進行需要完成兩個動作:
   (1) 告訴編譯器與DLL相對應的.lib文件所在的路徑及文件名,#pragma comment(lib,"dllTest.lib")就是起這個作用。程序員在 建立一個DLL文件時,連接器會自動為其生成一個對應的.lib文件,該文件包含了DLL 導出函數的符號名及序號(并不含有實際的代碼)。在應用程序 里,.lib文件將作為DLL的替代文件參與編譯。另外一種顯式調用的方式是設置vc中的目錄和includefiles來實現

 

   (2) 聲明導入函數,extern "C" __declspec(dllimport) add(int x,int y)語句中的__declspec(dllimport)發揮這個作 用。靜態調用方式不再需要使用系統API來加載、卸載DLL以及獲取DLL中導出函數的地址。這是因為,當程序員通過靜態鏈接方式編譯生成應用程序時,應 用程序中調用的與.lib文件中導出符號相匹配的函數符號將進入到生成的EXE 文件中,.lib文件中所包含的與之對應的DLL文件的文件名也被編譯器存儲在 EXE文件內部。當應用程序運行過程中需要加載DLL文件時,Windows將根據這些信息發現并加載DLL,然后通過符號名實現對DLL 函數的動態鏈接。這 樣,EXE將能直接通過函數名調用DLL的輸出函數,就象調用程序內部的其他函數一樣。

 

2.1.3 DllMain函數

 

Windows在加載dll的時候,會首先需要一個入口函數DllMain。當在dll中不定義DllMain的時候,windows會從其他運行庫中調用一個不做任何操作的DllMain函數,直接返回true。DllMain是dll內部的函數,這意味著在調用dll的程序中不能顯式的調用。它是在 dll被調用時自動被調用的。
 

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)

{
switch (ul_reason_for_call)
{
case: DLL_PROCESS_ATTACH:
break;
case: DLL_THREAD_ATTACH:
break;
case: DLL_THREAD_DETACH:
break;
case: DLL_PROCESS_DETACH:
break;
return TRUE;
}

 

2.2 在dll中導出變量
1、在dll中定義變量 extern int global;
2、在.def中定義輸出 EXPORTS:
global DATA
3、 在應用程序中調用:#pragma comment(lib,"dllTest.lib")
extern int global;
注意在此引入的變量global,是一個地址,在使用時需要強制轉化為指針后再用,才能得到其值。
(int *)global=10;
 

在應用工程中引用DLL中全局變量的一個更好方法是:

extern int _declspec(dllimport) global; //用_declspec(dllimport)導入
通過_declspec(dllimport)方式導入的就是DLL中全局變量本身而不再是其地址了,建議在一切可能的情況下使用這種方式。

 

2.3 dll導出類
在定義的時候用

class _declspec(dllexport) classname{

}

 

在類中引用的時候用加入類定義頭文件:

 

#include “classname.h”

Class _declspec(dllimport) classname 來導入類

 

3、 MFC規則Dll
MFC規則DLL的概念體現在兩方面:
   (1) 它是MFC的
   “是MFC的” 意味著可以在這種DLL的內部使用MFC;
(2) 它是規則的
“是規則的”意味著它不同于MFC擴展DLL,在MFC規則DLL的內部雖然可以使用MFC,但是其與應用程序的接口不能是MFC。而MFC擴展DLL與應用程序的接口 可以是MFC,可以從MFC擴展DLL中導出一個MFC類的派生類。
   Regular DLL能夠被所有支持DLL技術的語言所編寫的應用程序調用,當然也包括使用MFC的應用程序。在這種動態連接庫中,包含一個從CWinApp繼承下 來的類,DllMain函數則由MFC自動提供。

 

(1)靜態鏈接到MFC 的規則DLL
   靜態鏈接到MFC的規則DLL與MFC庫(包括MFC擴展 DLL)靜態鏈接,將MFC庫的代碼直接生成在.dll文件中。在調用這種DLL的接口時,MFC使用DLL的資 源。因此,在靜態鏈接到MFC 的規則DLL中不需要進行模塊狀態的切換。使用這種方法生成的規則DLL其程序較大,也可能包含重復的代碼。
(2)動態鏈接到MFC 的規則DLL
   動態鏈接到MFC 的規則DLL 可以和使用它的可執行文件同時動態鏈接到 MFC DLL 和任何MFC擴展 DLL。在使用了MFC共享庫的時候,默認情況下,MFC 使用主應用程序的資源句柄來加載資源模板。這樣,當DLL和應用程序中存在相同ID的資源時(即所謂的資源重復問題),系統可能不能獲得正確的資源。因此,對于共 享MFC DLL的規則DLL,我們必須進行模塊切換以使得MFC能夠找到正確的資源模板。

我們可以在Visual C++中設置MFC規則DLL是靜態鏈接到MFC DLL還是動態鏈接到MFC DLL。如圖8,依次選擇Visual C++的project -> Settings -> General菜單或選項,在Microsoft Foundation Classes中進行設置。

 

3.1規則DLL的創建;

與非MFCdll不同的是,在其定義里面可以引入MFC類,其他與非MFC一樣
 

3.2規則DLL的調用

(1)顯示方式LoadLibrary , GetProcAdress , FreeLibrary

(2)我們照樣可以在EXE程序中隱式調用MFC規則DLL,只需要將DLL工程生成的.lib文件和.dll文件拷入當前工程所在的目錄,并在cpp文件頂部添加:
#pragma comment(lib,"RegularDll.lib")
 

3.3共享MFC DLL的規則DLL的模塊切換

應用程序進程本身及其調用的每個DLL模塊都具有一個全局唯一的HINSTANCE句柄,它們代表了DLL或EXE模塊在進程虛擬空間中的起始地址進程本身的模塊句柄一般為0x400000而DLL模塊的缺省句柄為0x10000000如果程序同時加載了多個DLL,則每個DLL模塊都會有不同的 HINSTANCE應用程序在加載DLL時對其進行了重定位。
  共享MFC DLL(或MFC擴展DLL)的規則DLL涉及到HINSTANCE句柄問題,HINSTANCE句柄對于加載資源特別重要。EXE和DLL都有其自己的資源,而且這些資源的ID可能重復,應用程序需要通過資源模塊的切換來找到正確的資源。如果應用程序需要來自于DLL的資源,就應將資源模塊句柄指定為 DLL的模塊句柄;如果需要EXE文件中包含的資源,就應將資源模塊句柄指定為EXE的模塊句柄。

 

模塊的切換有三種方式:
(1)在DLL函數中調用:AFX_MANAGE_STATE(AfxGetStaticModuleState());(推薦使用,最簡單)
void ShowDlg(void)
{
//方法1:在函數開始處變更,在函數結束時恢復
//將AFX_MANAGE_STATE(AfxGetStaticModuleState());作為接口函數的第一//條語句進行模塊狀態切換
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog dlg(IDD_DLL_DIALOG);//打開ID為2000的對話框
dlg.DoModal();
}
(2)在DLL函數中調用AfxGetResourceHandle();
AfxSetResourceHandle(HINSTANCE xxx);
(3)由應用程序自身切換(不推薦,最麻煩)
 

4、擴展MFCDLL

MFC擴展DLL的內涵為MFC的擴展,用戶使用MFC擴展DLL就像使用MFC本身的DLL一樣。除了可以在MFC擴展DLL的內部使用MFC以外, MFC擴展DLL與應用程序的接口部分也可以是MFC。我們一般使用MFC擴展DLL來包含一些MFC的增強功能,譬如擴展MFC的CStatic、 CButton等類使之具備更強大的能力。
導出一個類,直接在類聲明頭文件中使用AFX_EXT_CLASS即可,最后別忘了在調用dll的程序中加入class的頭文件

 

5、總結:
綜上所述:以上幾種dll主要由以下幾種區別:
 

1、動態鏈接庫是將exe程序在程序執行的時候動態加載的,而靜態鏈接庫是在編譯的時 將其編譯在代碼之中的

2、動態鏈接庫可以輸出變量、函數和類。其中每種輸出的方式與調用方式不盡相同:

 

(1)變量:在dll中定義 extern int global;
在.def文件中輸出 EXPORTS
global DATA
或extern _declspec(dllexport)int global(不用輸出文件了)
在程序中調用:
靜態調用:

#pragma comment(lib,"dllTest.lib")

extern int _declspec(dllimport) global;
動態調用:
 

(2)函數:在dll中定義

extern “C” __declspec(dllexport) int add(int a, int b);
也可以在.def文件中輸出該函數
EXPORTS
add @ 1
在程序中調用:
靜態調用:
#pragma comment(lib,"dllTest.lib")
extern "C" __declspec(dllimport) add(int x,int y);
動態調用:
typedef int(*lpAddFun)(int, int); //宏定義函數指針類型
lpAddFun add;//函數指針
HINSTANCE hDll=LoadLibrary(“path”);
add=(lpAddFun)GetProcAddress(hDll, "add");//獲得dll中的add函數指針
FreeLibrary(hDll);
在從dll調用中返回的函數、指針或者類都是以指針的方式會的,即返回的是函數、變量或類的地址。這里一定要注意,不能簡單的用函數名來賦值。
(3)類:在dll中定義:
在定義的時候用 class _declspec(dllexport) classname{
}
在類中引用的時候用
加入類定義頭文件:#include “classname.h”
Class _declspec(dllimport) classname 來導入類
3、除了擴展MFC的dll外,其他的dll均可被其他語言編寫的應用程序來調用。

 

posted on 2012-05-09 14:34 Tim 閱讀(2815) 評論(0)  編輯 收藏 引用 所屬分類: 資源共享C/C++語言

<2012年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:www.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            91久久综合亚洲鲁鲁五月天| 久久精品一区二区三区中文字幕| 亚洲综合好骚| 午夜精彩国产免费不卡不顿大片| 欧美三级在线视频| 一区二区三区日韩精品| 亚洲欧美日韩精品在线| 国产精品夜夜夜一区二区三区尤| 欧美在线播放视频| 亚洲电影免费观看高清完整版| 最新亚洲一区| 欧美精品亚洲精品| 亚洲宅男天堂在线观看无病毒| 久久国产高清| 亚洲国产中文字幕在线观看| 欧美日韩美女一区二区| 香蕉久久a毛片| 亚洲欧洲精品一区二区精品久久久| 99精品欧美一区二区三区| 国产精品美女主播在线观看纯欲| 亚洲综合好骚| 久久蜜桃精品| 午夜免费久久久久| 亚洲精品资源美女情侣酒店| 欧美午夜a级限制福利片| 猛男gaygay欧美视频| 一本色道久久综合狠狠躁篇怎么玩| 欧美综合国产| 欧美精品一区二区三区久久久竹菊 | 国产精品激情电影| 91久久国产综合久久| 亚洲电影免费观看高清完整版在线| 午夜电影亚洲| 久久久久久欧美| 精品1区2区3区4区| 久久尤物视频| 一区二区三区在线视频观看| 国产精品久久久久婷婷| 欧美日韩视频在线一区二区观看视频 | 亚洲午夜电影在线观看| 国产在线精品二区| 亚洲美女啪啪| 亚洲欧美电影在线观看| 亚洲另类在线一区| 欧美日韩国产综合久久| 99亚洲一区二区| 欧美激情在线有限公司| 久久综合久久久久88| 亚洲国产中文字幕在线观看| 国产视频一区三区| 夜夜嗨av一区二区三区| 久色婷婷小香蕉久久| 午夜在线视频观看日韩17c| 欧美日韩直播| 亚洲免费影院| 亚洲视屏在线播放| 国产欧美综合一区二区三区| 亚洲女性裸体视频| 亚洲免费视频网站| 国产麻豆日韩欧美久久| 久久国产毛片| 久久久人成影片一区二区三区观看 | 国产一区二区三区四区hd| 亚洲欧美伊人| 久久久五月婷婷| 亚洲欧洲精品天堂一级| 欧美大色视频| 亚洲影院在线观看| 欧美日韩a区| 亚洲国产欧美国产综合一区| 亚洲最黄网站| 欧美黄色免费| 欧美国产免费| 亚洲摸下面视频| 亚洲欧美中日韩| 亚洲高清在线视频| 国产精品vip| 快播亚洲色图| 在线亚洲伦理| 亚洲国产99| 久久精品91| 亚洲一区二区三区中文字幕| 在线成人av.com| 国产精品人人做人人爽| 欧美激情精品| 久久久久久久久久久久久久一区| 亚洲线精品一区二区三区八戒| 欧美国产日韩精品免费观看| 久久国产精品久久久久久久久久| 99在线精品视频在线观看| 红桃av永久久久| 国产欧美一区视频| 国产精品高潮久久| 欧美久久久久免费| 免费观看久久久4p| 欧美专区中文字幕| 午夜精品久久久久影视| 一区二区日韩| 99国产精品久久久久久久成人热| 欧美激情按摩在线| 欧美成人精品1314www| 久久一区欧美| 久久精品一本久久99精品| 午夜在线一区二区| 亚洲欧美综合国产精品一区| 亚洲午夜国产成人av电影男同| 亚洲免费观看高清在线观看| 亚洲精品乱码久久久久久黑人| 亚洲丁香婷深爱综合| 亚洲成色777777女色窝| 国内外成人在线| 黄页网站一区| 激情综合在线| 在线播放中文一区| 亚洲激情av| 亚洲人成在线观看| 日韩一区二区精品在线观看| 日韩视频在线观看免费| 一二三四社区欧美黄| 中文久久乱码一区二区| 亚洲素人一区二区| 午夜精品区一区二区三| 欧美在线999| 玖玖综合伊人| 欧美成熟视频| 亚洲精品免费在线播放| 一区二区三区国产盗摄| 亚洲一区二区四区| 欧美在线视频网站| 久色成人在线| 欧美日韩国产色视频| 国产精品成人免费| 国产一区白浆| 亚洲激情啪啪| 亚洲一本视频| 久久久欧美一区二区| 欧美电影在线观看| 亚洲精品综合在线| 午夜精品999| 欧美韩日高清| 国产精品一区三区| 最新日韩在线| 亚洲欧美日韩精品久久亚洲区| 久久久精品日韩欧美| 亚洲激情第一页| 亚洲欧美国产另类| 欧美va天堂在线| 国产精品夜夜嗨| 亚洲人成毛片在线播放| 亚洲欧美在线一区| 亚洲第一精品福利| 午夜精品久久久久久| 欧美激情国产日韩精品一区18| 国产精品免费观看视频| 亚洲区欧美区| 久久久99久久精品女同性| 91久久国产综合久久| 欧美伊人久久久久久久久影院| 欧美精品午夜| 极品中文字幕一区| 亚洲曰本av电影| 亚洲第一在线综合网站| 欧美一区二区三区四区夜夜大片 | 欧美怡红院视频一区二区三区| 米奇777超碰欧美日韩亚洲| 国产精品视频yy9299一区| 亚洲人成亚洲人成在线观看图片| 欧美专区日韩视频| 99伊人成综合| 美女露胸一区二区三区| 国产婷婷97碰碰久久人人蜜臀| 亚洲免费精彩视频| 欧美高清自拍一区| 欧美伊人久久大香线蕉综合69| 欧美特黄一区| 亚洲人精品午夜| 久久偷窥视频| 欧美亚洲综合在线| 国产精品一区二区三区乱码 | 免费黄网站欧美| 亚洲免费在线观看| 国产精品草莓在线免费观看| 亚洲国产欧美不卡在线观看| 久久免费国产| 久久成人在线| 国产日本欧美一区二区三区| 亚洲淫性视频| 9久re热视频在线精品| 欧美区国产区| 日韩一二三区视频| 亚洲精品日韩久久| 欧美精品一区二区三区视频 | 一区二区三区欧美激情| 亚洲国产一区二区a毛片| 另类激情亚洲| 亚洲人妖在线| 亚洲精品久久久久久久久久久| 久久女同精品一区二区| 亚洲高清一区二| 欧美激情1区2区|