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

山寨:不是最好的,是最適合我們的!歡迎體驗山寨 中文版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.def。EXPORTS下所寫函數名如與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 這個就是我們要的了。其它參數請看說明?,F在我們在使用某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>
            国产欧亚日韩视频| 国内精品久久久久国产盗摄免费观看完整版| 精品成人a区在线观看| 久久成人av少妇免费| 欧美一区二区高清在线观看| 黄色一区三区| 亚洲国产婷婷综合在线精品 | 欧美伊人久久久久久久久影院| 一区二区三区视频在线| 国产日韩精品一区二区三区| 久久人人爽人人爽爽久久| 鲁大师影院一区二区三区| 亚洲伦理久久| 亚洲一区二区四区| 在线观看欧美激情| 99国产精品久久久久老师| 国产日韩欧美在线一区| 亚洲第一毛片| 久久av免费一区| 久久精品av麻豆的观看方式| 91久久夜色精品国产网站| 在线亚洲免费| 1024精品一区二区三区| 在线视频精品一| 伊人影院久久| 一区二区三区四区国产| 亚洲第一视频网站| 亚洲视频碰碰| 亚洲欧洲日韩综合二区| 亚洲欧美在线一区| 在线视频亚洲| 美日韩丰满少妇在线观看| 香蕉成人伊视频在线观看| 另类天堂av| 香蕉久久夜色精品| 欧美区一区二| 欧美aaa级| 国产欧美日韩三级| 洋洋av久久久久久久一区| 亚洲国产精品电影在线观看| 亚洲在线视频网站| 一区二区欧美视频| 欧美a级在线| 免费视频一区| 国产亚洲欧美一区| 亚洲一区二区网站| 亚洲一区二区动漫| 欧美精品激情在线观看| 欧美肥婆bbw| 亚洲电影欧美电影有声小说| 亚洲欧美中文在线视频| 亚洲尤物在线| 欧美日韩一二三四五区| 亚洲国产欧美日韩| 亚洲国产网站| 美女性感视频久久久| 久久久久久亚洲综合影院红桃 | 亚洲欧美日韩视频一区| 亚洲深夜福利网站| 欧美噜噜久久久xxx| 亚洲国产一区在线观看| 亚洲国产成人av好男人在线观看| 久久精品成人一区二区三区蜜臀 | 国语精品中文字幕| 欧美专区亚洲专区| 久久免费国产| 一区二区视频欧美| 美女视频一区免费观看| 欧美成人有码| 亚洲精品一区二区在线| 欧美电影在线观看完整版| 亚洲国产精品一区二区第四页av | 亚洲丰满在线| 欧美99久久| 日韩午夜电影在线观看| 亚洲一二三区在线| 国产精品ⅴa在线观看h| 亚洲影视在线播放| 久久久亚洲综合| 亚洲国产成人久久| 欧美极品在线观看| 一区二区三区精品视频| 久久精品2019中文字幕| 激情久久一区| 欧美精品一区二区三区视频| 一区二区三区欧美| 久久人人爽国产| 亚洲美女网站| 国产精品一级| 久久亚洲精品视频| 99视频一区二区| 久久久www成人免费无遮挡大片 | 亚洲国产精品久久久久婷婷884| 免费观看一级特黄欧美大片| 日韩视频免费在线| 欧美一区午夜精品| 亚洲欧洲精品一区二区精品久久久| 欧美精品一区二区三区蜜桃| 亚洲欧美日韩爽爽影院| 欧美成人免费网站| 午夜精品久久久久久久99热浪潮| 国内精品久久久久影院优| 欧美精品在线网站| 欧美一区视频在线| 亚洲免费高清视频| 久久中文欧美| 亚洲综合色视频| 最新热久久免费视频| 国产精品热久久久久夜色精品三区| 久久久久久91香蕉国产| 一本色道综合亚洲| 亚洲成人在线网站| 久久精品国产成人| 亚洲影视中文字幕| 亚洲人成艺术| 在线成人中文字幕| 国产日韩欧美中文| 欧美午夜电影一区| 欧美大秀在线观看| 久久青青草原一区二区| 亚洲欧美日韩区| 一区二区三区免费看| 亚洲国产美女| 男人插女人欧美| 久久久91精品国产一区二区精品| 国产精品99久久久久久www| 亚洲国产一二三| 精品成人久久| 国内自拍一区| 国产综合色一区二区三区| 国产精品欧美精品| 国产精品久久久久高潮| 欧美日韩在线一区| 欧美日产国产成人免费图片| 欧美成人一区二区三区片免费| 久久久久久91香蕉国产| 久久激情久久| 久久久水蜜桃| 久久男人资源视频| 久久综合影音| 裸体素人女欧美日韩| 蜜桃av噜噜一区| 欧美国产一区二区三区激情无套| 免费成人高清视频| 欧美国产精品va在线观看| 欧美成人网在线| 欧美日韩国产精品一区| 欧美麻豆久久久久久中文| 欧美精品一区在线发布| 欧美片网站免费| 国产精品成人午夜| 国产精品一区久久| 国产一区视频在线看| 在线视频国产日韩| 亚洲人成在线观看| 亚洲一区二区日本| 午夜精品视频网站| 久久手机精品视频| 欧美激情一区二区三区高清视频 | 久久精品一区蜜桃臀影院 | 欧美亚洲免费在线| 久久久久一区二区三区| 免费av成人在线| 亚洲娇小video精品| 亚洲午夜av电影| 欧美在线视频一区| 欧美黄网免费在线观看| 欧美视频不卡| 国产一区二区三区高清| 亚洲激情电影中文字幕| 一区二区三区四区五区视频| 性欧美大战久久久久久久久| 美女黄色成人网| 日韩午夜免费| 久久www成人_看片免费不卡| 欧美二区在线看| 国产精自产拍久久久久久蜜| 亚洲第一精品久久忘忧草社区| 一区二区三区四区精品| 久久精品一区二区国产| 91久久综合| 欧美专区在线观看| 欧美日韩国产另类不卡| 激情六月综合| 亚洲欧美精品伊人久久| 欧美成人午夜激情在线| 亚洲综合第一页| 欧美精品国产一区二区| 国产视频精品va久久久久久| 亚洲国产一区二区精品专区| 小黄鸭精品密入口导航| 亚洲高清免费| 久久国产精品99久久久久久老狼| 欧美日本精品一区二区三区| 经典三级久久| 欧美资源在线观看| 一区二区三区精品在线| 欧美精品18+| 亚洲国产婷婷综合在线精品 | 欧美在线视频一区二区三区|