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

山寨:不是最好的,是最適合我們的!歡迎體驗山寨 中文版MSDN

Blog @ Blog

當華美的葉片落盡,生命的脈絡才歷歷可見。 -- 聶魯達

常用鏈接

統計

積分與排名

BBS

Blog

Web

最新評論

VC之DLL編程

DLL編程

靜態鏈接:每個應用程序使用函數庫,必須擁有一份庫的備份。多個應用程序運行時,內存中就有多份函數庫代碼的備份。

動態連接庫:多個應用程序可以共享一份函數庫的備份。

 

DLL的調用方式:DLL的使用者在調用庫中輸出函數時,函數參數的壓棧和出棧順序和方法。

VC++支持四種方式:

<1>_cdecl調用方式: 也叫C調用方式,函數參數的壓棧順序是從右至左,參數的出棧方式由調用者完成,在調用DLL的函數的地方都應包含清空堆棧的代碼,它是C/C++缺省的調用方式。

<2>_stdcall標準調用方式:函數參數壓棧順序是從右至左,參數出棧工作由被調用者負責完成。系統將加在函數原型定義前的”WINAPI”宏翻譯為適當的調用方式,對于Win32_stdcall調用方式。

<3>_fastcall:主要特點是調用速度快,被調用的函數參數傳遞不依靠堆棧,而是通過寄存器,但并不是對所有的參數傳遞均使用寄存器,往往只是用ECXEDX傳送前兩個雙字或比較小的參數,其余的參數傳遞仍然采用從右至左壓棧方式,出棧工作由被調用的函數完成。

<4>thiscall:前三種是關鍵字,可以加到函數前作修飾,thiscall不是關鍵字,因此程序中不能顯式寫入,這種方式僅應用于C++成員函數,thisC++中指向對象的指針,this存放在ECX寄存器中,參數從右至左壓棧,出棧由被調用者完成。

 

DLL的入口函數

DllMain()函數負責完成DLL的初始化和解說DLL調用后的清理工作。當加載DLL時,如存在DllMain()函數則調用它。

 

MFC DLL

  MFC DLL可以讓我們的程序使用MFC庫,它分為3類:

<1>Regular Dll with MFC Statically linked   (正規)

     靜態鏈接MFC庫,在DLL工程中將包含工程中所需的MFC庫代碼的拷貝,因此,程序可以脫離MFC庫使用。

<2>Regular Dll using shared MFC Dll        (正規)

     動態共享MFC庫,工程必須在裝有MFC庫的機器上才能運行。

MFC正規DLL編寫注意問題:

     應在輸出函數的函數體內首先加入:

     AFX_MANAGE_STATE(AfxGetStaticModuleState());

<3>MFC Extension Dll(using shared MFC Dll)     (擴展)

     它不但能輸出函數,還能輸出類,用戶可以直接使用、繼承這個輸出類,但它不是正規DLL,如果要讓非VC++程序調用,必須使用正規DLL

MFC擴展DLL編寫注意問題:

     <1>在要輸出的類定義中加入:AFC_EXT_CLASS

         如:class AFX_EXT_CLASS  cls{};

     <2>在要輸出的函數定義前加入:AFC_EXT_CLASS

         如:AFX_EXT_CLASS int  func(){}

 

自行編寫DLL的方法

    <1>DLL中編寫的函數前加上”__declspec(dllexport)”即可導出該函數。

<2>DLL中導出類,是在class和類名之間加入”__declspec(dllexport)”,如果只想導出類中指定的函數,可只在該函數前加上”__declspec(dllexport)”

<3>C++為支持函數重載,采用了名稱壓軋,因此,DLL文件在編譯時,函數名會發生改變,為保證對DLL的正確訪問,可在”__declspec(dllexport)”聲明之前加入”extern “c””,編譯時就不會發生名稱改變,但extern “c”只能用于導出全局函數,不能導出類的成員,如果在函數名前加入了調用約定(如:_stdcall),編譯時還是會發生名稱改變。

         也可通過模塊定義文件的方式解決名稱改變的問題,模塊定義文件的后綴為”.def”,步驟如下:

         1新建一個文本文檔,改名為”x.def”

         2x.def加入到工程;

3編輯x.defEXPORTS下所寫函數名如與DLL文件中函數名相同,則以所寫名稱導出該函數。

    <4>DLL通過GetForegroundWindow()獲得正在使用它的前景窗口的句柄。

    <5>GetModuleHandle()得到一個DLL的句柄。

        GetSystemMetrics()獲取系統信息。

 

系統對DLL中可改變的數據,在進程寫訪問時會拷貝到一個新的數據頁面,如果多個進程要共享該數據,可設置節,創建節后,將數據放到節中且必須初始化:

#pragma     data_seg(“name”)          //開頭

    //數據

#pragma     data_seg()      //結尾

#pragma     comment(linker,”/section:name,RWS”)

    //設為讀、寫、共享,也可寫在.def文件中。

 

使用DLL

    要使用DLL,首先要將DLL文件映像到用戶進程的地址空間中,并聲明被調用的函數,然后才能進行函數調用,調用方法與一般函數相同。

    DLL映像到進程地址空間的方法:

    <1>隱式的加載時鏈接

        DLL工程經編譯后,產生一個.dll文件,一個.lib文件及一個包含DLL輸出函數聲明的.h頭文件,隱式調用DLL就是將這個.lib文件鏈接到工程中。

        lib文件中包含了DLL允許調用的所有函數列表,鏈接器發現程序調用了lib文件中列出的某個函數時,會在程序的可執行文件的文件映像中加入包含這個函數的DLL文件的名字信息,當程序運行時,可執行文件被操作系統產生映像文件,系統會查看這個映像文件中關于DLL的信息,然后將這個DLL文件映像到進程的地址空間。

    鏈接lib文件的方法:

1加入到文件列表

2Link項下加入

3#pragma   comment(lib,”mydll.lib”)

<2>顯式的運行時鏈接步驟如下:

1LoadLibrary()AfxLoadLibrary()加載DLL或可運行模塊;

2GetProcAddress()得到要調用的DLL中函數的指針,然后使用該函數;

3使用完DLL以后,用FreeLibrary()DLL在進程的映射解除,減少加載DLL的記數。

    被調用的函數聲明的方法有三種:

    <1>”extern”聲明被調用函數。

    <2>使用”__declspec(dllimport)”聲明,即告訴編譯器,所引用的函數或文件是從DLL中輸入的,編譯器能生成運行效率更高的代碼。

    <3>也可將聲明放在DLL編寫的頭文件中,在使用的文件中包含該頭文件即可。

 

 

要使用DLL中導出的類,必須在使用的文件中包含該類所在的頭文件!

盡量導出方法(做接口)少導出類。

標準DLL中導出函數的寫法:

extern "C"  BOOL __declspec(dllexport) EXPORT ShowDlg()   ///標準導出函數格式

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());//些宏不可少!

    // 此處為普通函數體

}

1.AfxGetStaticModuleState()指向當前模塊狀態;

2.當前函數調用結束后原模塊的狀態自動被恢復;

3.用于DLL中所調用MFC函數、類、資源時的模塊狀態切換

并在def文件中定義導出函數的序號:ShowDlg @1

在調用處寫如下代碼:

typedef void (*dllfun)(); //定義函數指針類型

HINSTANCE   hlib= NULL;

hlib=LoadLibrary("std_dll.dll"); //加載庫

dllfun  ShowDlg  = NULL;//定義函數指針

ShowDlg=(dllfun)GetProcAddress(hlib,"ShowDlg");//獲取庫中函數地址

ShowDlg();  //調用函數

 

 

擴展DLL導出類的寫法:

class AFX_EXT_CLASS  clsName{};

擴展DLL中的資源使用

簡單的說:每個DLL有自己特有的資源。在使用時,明確的告訴系統要使用哪個DLL的資源。現在的問題就是如何告訴系統使用哪個DLL的資源。函數:AfxSetResourceHandle() 可以完成這個功能。參數是資源的句柄。

那怎么得到某個DLL的資源句柄呢?如下:

在擴展DLL的入口函數

extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

 {

if (!AfxInitExtensionModule(ShpSymbolDLL, hInstance))

       return 0;

}

其中ShpSymbolDll 可能會因工程名不同而不同,這里就以這個名稱代替來說明了,DLL的資源句柄就可以在此得到。

 ShpSymbolDLL 定義:

 AFX_EXTENSION_MODULE ShpSymbolDLL  = { NULL, NULL };

ShpSymbolDLL.hResource 這個就是我們要的了。其它參數請看說明。現在我們在使用某DLL的資源時只要先加入以下兩行就可以正確執行了:

HINSTANCE hOld = AfxGetResourceHandle();

AfxSetResourceHandle( ShpSymbolDLL.hResource );

注意在用完之后再恢復:

AfxSetResourceHandle( hOld );

另外一個不得不提起的東西,在入口函數中有一行

new CDynLinkLibrary(ShpSymbolDLL);

旁邊有一說明:將此 DLL 插入到資源鏈中。

的確如此。言下之意,上面所說的沒什么用了?其實不然,假如DLL中有一個Dialog ID120,在你調用此DLL的應用程序資源中,如果沒有ID的值為120。那么,上面的都是白做了,你會得到預料中的結果。但如果應用程序中有一相同ID的對話框資源呢?請大家一試。結果就不一樣了。其中的原因與new CDynLinkLibrary(ShpSymbolDLL) 相關聯。

具體請看MFC中 的代碼 DoModal() 就會得到解答。或看MSDN中帶的例子 dllhusk,系統自動會查找相應的資源,但不會判斷哪個是正確的。以找到的第一個資源為準。

另:為了編寫方便,可以寫一個類 ,寫成全局的。

class CModuleInfo

{public:

   HMODULE    m_hModule;

   HMODULE    m_hResource;

 public:

   CModuleInfo(void){}

   ~CModuleInfo(void){}

 };

class AFX_EXT_CLASS CModuleStateMana

{

   HINSTANCE m_hInstOld;

 public:

   CModuleStateMana();

   ~CModuleStateMana();

};

實現如下:

 CModuleInfo  s_mi;

 CModuleStateMana::CModuleStateMana()

{

   m_hInstOld = AfxGetResourceHandle();

   AfxSetResourceHandle( s_mi.m_hModule );

 }

CModuleStateMana::~CModuleStateMana()

{

   AfxSetResourceHandle( m_hInstOld );

}

然后在入口函數之前加入

extern CModuleInfo s_mi;

函數中加入:

     s_mi.m_hModule   = ShpSymbolDLL.hModule;

     s_mi.m_hResource= ShpSymbolDLL.hResource;

在調用的時候只要先加入:

 CModuleStateMana msm;

就可以正確調用了。

posted on 2008-06-20 14:07 isabc 閱讀(914) 評論(0)  編輯 收藏 引用 所屬分類: C++基礎

廣告信息(免費廣告聯系)

中文版MSDN:
歡迎體驗

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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久久久久久久vr| 欧美婷婷六月丁香综合色| 亚洲男人的天堂在线aⅴ视频| 亚洲香蕉在线观看| 国产亚洲欧美一区二区三区| 另类成人小视频在线| 免费成人毛片| 亚洲亚洲精品在线观看| 亚洲一区二区三| 国产在线拍偷自揄拍精品| 欧美fxxxxxx另类| 欧美猛交免费看| 欧美一区永久视频免费观看| 久久久av网站| 日韩亚洲视频| 午夜在线精品偷拍| 亚洲精品影视| 亚洲一区在线观看视频 | 欧美午夜激情视频| 久久riav二区三区| 美女久久网站| 亚洲欧美在线另类| 久久青草欧美一区二区三区| av成人国产| 小处雏高清一区二区三区| 亚洲国产精品一区二区久| 亚洲影院一区| 日韩视频二区| 久久国产精品高清| 亚洲图片欧洲图片日韩av| 久久精品人人| 午夜欧美电影在线观看| 欧美1区免费| 久久久久国产精品厨房| 欧美视频网址| 91久久精品美女| 国产精品夜夜夜一区二区三区尤| 欧美激情自拍| 国产午夜精品美女毛片视频| 亚洲精品影视| 在线欧美日韩精品| 欧美一区二区精美| 亚洲一区日韩在线| 快she精品国产999| 性欧美18~19sex高清播放| 欧美精品一区二区三区久久久竹菊| 久久久精品国产一区二区三区| 国产精品成人一区二区三区夜夜夜| 欧美成人在线影院| 狠狠干综合网| 欧美在线1区| 久久xxxx| 国产精品毛片高清在线完整版| 亚洲欧洲日本专区| 亚洲精品久久嫩草网站秘色| 久久精品国产99精品国产亚洲性色 | 久久久久久综合网天天| 欧美中文日韩| 国产精品自拍视频| 中国亚洲黄色| 亚洲欧美视频在线观看| 国产精品久久久久久亚洲毛片| 日韩视频在线观看| 亚洲天堂免费观看| 欧美日在线观看| 亚洲视频axxx| 午夜宅男久久久| 国产日本欧美一区二区| 午夜老司机精品| 久久久久久久久久久久久9999| 国产视频精品va久久久久久| 欧美一区二区播放| 久久综合中文| 亚洲日本成人女熟在线观看| 欧美国产日韩视频| 一区二区激情| 久久99在线观看| 在线观看中文字幕不卡| 美日韩精品免费| 日韩一区二区精品视频| 亚洲影视在线| 国产小视频国产精品| 老司机aⅴ在线精品导航| 亚洲精品裸体| 午夜一区二区三区在线观看| 韩国av一区二区三区在线观看| 久久久亚洲高清| 亚洲精品国产精品乱码不99| 亚洲综合视频网| 国内精品亚洲| 欧美精品麻豆| 香蕉久久夜色精品国产| 欧美夫妇交换俱乐部在线观看| 99视频+国产日韩欧美| 国产精品日韩电影| 另类图片综合电影| 在线视频精品| 免费观看成人www动漫视频| 一区二区免费在线视频| 国产欧美一区二区三区在线老狼| 久久亚洲影院| 亚洲永久在线观看| 亚洲国产精品女人久久久| 亚洲免费一区二区| 亚洲激情网址| 国产视频一区免费看| 欧美日本国产视频| 久久精品国产久精国产爱| 亚洲三级免费| 免费观看亚洲视频大全| 亚洲欧美日韩直播| 亚洲国语精品自产拍在线观看| 国产精品日韩高清| 欧美激情在线| 卡一卡二国产精品| 欧美影视一区| 一区二区三区精品视频在线观看| 欧美电影免费网站| 久久精品一区二区国产| 亚洲香蕉网站| 亚洲美女在线看| 影音先锋国产精品| 国产亚洲福利社区一区| 国产精品国产三级国产 | 亚洲欧美日韩一区二区在线| 亚洲黄色小视频| 美女主播视频一区| 久久av二区| 欧美一级成年大片在线观看| 亚洲午夜久久久久久久久电影网| 亚洲级视频在线观看免费1级| 韩国av一区二区三区四区| 国产精品福利在线观看| 欧美视频在线观看一区| 欧美精品在欧美一区二区少妇| 猫咪成人在线观看| 卡通动漫国产精品| 美女视频黄a大片欧美| 久久夜色撩人精品| 久久久久久尹人网香蕉| 久久精品亚洲精品| 欧美在线啊v| 久久gogo国模啪啪人体图| 午夜精品国产精品大乳美女| 亚洲小说欧美另类社区| 一区二区国产日产| 亚洲午夜女主播在线直播| 亚洲深夜福利在线| 午夜精品久久久久久久久 | 亚洲国产激情| 亚洲国产精品黑人久久久 | 久久国产精品亚洲va麻豆| 久久se精品一区精品二区| 久久激情视频久久| 久久深夜福利| 欧美激情第六页| 亚洲人在线视频| 一本久久精品一区二区| 亚洲深夜福利| 久久成人精品| 蜜臀av一级做a爰片久久 | 欧美一区国产一区| 久久久久久夜| 欧美激情一区在线观看| 国产精品久久久久久五月尺| 国产视频久久久久| 亚洲激情国产| 亚洲尤物精选| 久久婷婷蜜乳一本欲蜜臀| 欧美激情久久久久久| 日韩亚洲欧美成人一区| 欧美亚洲一区三区| 欧美chengren| 国产毛片久久| 亚洲日本激情| 欧美在线观看视频在线| 欧美成熟视频| 亚洲午夜电影网| 久久久午夜电影| 国产精品国产| 亚洲黄页一区| 午夜视频久久久| 欧美福利电影网| 亚洲欧洲99久久| 欧美精品日本| 曰韩精品一区二区| 亚洲欧美在线一区二区| 欧美成人一区二区在线| 亚洲永久精品大片| 欧美国产日产韩国视频| 韩国三级电影一区二区| 亚洲一二三区视频在线观看| 欧美成人嫩草网站| 亚洲欧美日韩精品久久奇米色影视 | 久久人体大胆视频| 国产精品蜜臀在线观看| 日韩天天综合|