




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、C#如何調用動態鏈接庫DLL動態鏈接庫也稱為DLL即為"DynamicLinkLibrary的縮寫是MicrosoftWindows最重要的組成要素之一,翻開Windows系統文件夾,你會發現文件夾中有很多DLL文件,Windows就是將一些主要的系統功能以DLL模塊的形式實現.動態鏈接庫是不能直接執行的,也不能接收消息,它只是一個獨立的文件,其中包含能被程序或其它DLL調用來完成一定操作的函數方法.注:C即一般稱為“方法,但這些函數不是執行程序本身的一局部,而是根據進程的需要按需載入,此時才能發揮作用.DLL只有在應用程序需要時才被系統加載到進程的虛擬空間中,成為調用進程的一部分,
2、此時該DLL也只能被該進程的線程訪問,它的句柄可以被調用進程所使用,而調用進程的句柄也可以被該DLL所使用.在內存中,一個DLL只有一個實例,且它的編制與具體的編程語言和編譯器都沒有關系,所以可以通過DLL來實現混合語言編程.DLL函數中的代碼所創立的任何對象包括變量都歸調用它的線程或進程所有.下面列出了當程序使用DLL時提供的一些優點:11) 使用較少的資源當多個程序使用同一個函數庫時,DLL可以減少在磁盤和物理內存中加載的代碼的重復量.這不僅可以大大影響在前臺運行的程序,而且可以大大影響其他在Windows操作系統上運行的程序.2) 推廣模塊式體系結構DLL有助于促進模塊式程序的開發.這可
3、以幫助您開發要求提供多個語言版本的大型程序或要求具有模塊式體系結構的程序.模塊式程序的一個例如是具有多個可以在運行時動態加載的模塊的計帳程序.3) 簡化部署和安裝當DLL中的函數需要更新或修復時,部署和安裝DLL不要求重新建立程序與該DLL的鏈接.此外,如果多個程序使用同一個DLL,那么多個程序都將從該更新或修復中獲益.當您使用定期更新或修復的第三方DLL時,此問題可能會更頻繁地出現.每種編程語言調用DLL的方法都不盡相同,在此只對用C朝用DLL的方法進行介紹.首先,您需要了解什么是托管,什么是非托管.一般可以認為:非托管代碼主要是基于win32平臺開發的DLL,activeX的組件,托管代碼
4、是基于.net平臺開發的.如果您想深入了解托管與非托管的關系與區別,及它們的運行機制,請您自行查找資料,本文件在此不作討論.一調用DLL中的非托管函數一般方法首先,應該在C#言源程序中聲明外部方法,其根本形式是:DLLImport"DLL文件修飾符extern返回變量類型方法名稱參數列表其中:DLL文件:包含定義外部方法的庫文件.修飾符:訪問修飾符,除了abstract以外在聲明方法時可以使用的修飾符.返回變量類型:在DLL文件中你需調用方法的返回變量類型.方法名稱:在DLL文件中你需調用方法的名稱.參數列表:在DLL文件中你需調用方法的列表.注意:需要在程序聲明中使用System.
5、Runtime.InteropServices命名空間.DllImport只能放置在方法聲明上.DLL文件必須位于程序當前目錄或系統定義的查詢路徑中即:系統環境變量中Path所設置的路徑.返回變量類型、方法名稱、參數列表一定要與DLL文件中的定義相一致.假設要使用其它函數名,可以使用EntryPoint屬性設置,如:DllImport"user32.dll",EntryPoint="MessageBoxA"staticexternintMsgBoxinthWnd,stringmsg,stringcaption,inttype;其它可選的DllImport
6、Attribute屬性:CharSet指示用在入口點中的字符集,如:CharSet=CharSet.Ansi;SetLastError指示方法是否保存Win32"上一錯誤",如:SetLastError=true;ExactSpelling指示EntryPoint是否必須與指示的入口點的拼寫完全匹配,如:ExactSpelling=false;PreserveSig指示方法的簽名應當被保存還是被轉換,如:PreserveSig=true;CallingConvention指示入口點的調用約定,如:CallingConvention=CallingConvention.Win
7、api;此外,關于“數據封送處理及“封送數字和邏輯標量請參閱其它一些文章2.C勵子:1. 啟動VS.NET,新建一個工程,工程名稱為“Tzb,模板為“Windows應用程序.2. 在“工具箱"的"Windows窗體"項中雙擊"Button項,向"FormT'窗體中添加一個按鈕.3. 改變按鈕的屬性:Name為“B1,Text為“用DllImport調用DLL彈出提示框",并將按鈕B1調整到適當大小,移到適當位置.4. 在類視圖中雙擊“FormT',翻開"Form1.cs代碼視圖,在"namespac
8、eTzb"上面輸入"usingSystem.Runtime.InteropServices;:以導入該命名空間.5. 在“Form1.cs設計視圖中雙擊按鈕B1,在“B1_Click方法上面使用關鍵字static和extern聲明方法"MsgBoX,將DllImport屬性附加到該方法,這里我們要使用的是“user32.dll"中的"MessageBoxA函數,具體代碼如下:DllImport("user32.dll",EntryPoint="MessageBoxA")staticexternintMsg
9、Box(inthWnd,stringmsg,stringcaption,inttype);然后在“B1_Click方法體內添加如下代碼,以調用方法“MsgBox:MsgBox(0,"這就是用DllImport調用DLL彈出的提示框哦!","挑戰杯",0x30);6. 按“F5運行該程序,并點擊按鈕B1,便彈出如下提示框:(二)動態裝載、調用DLL中的非托管函數在上面已經說明了如何用DllImport調用DLL中的非托管函數,但是這個是全局的函數,假假設DLL中的非托管函數有一個靜態變量S,每次調用這個函數白時候,靜態變量S就自動加1.結果,當需要重新計數
10、時,就不能得出想要的結果.下面將用例子說明:1. DLL的創立1) 啟動VisualC+6.0;2) 新建一個“Win32Dynamic-LinkLibrary工程,工程名稱為“Count"3) 在"Dllkind選擇界面中選擇"Asimpledllproject"4) 翻開Count.cpp,添加如下代碼:/導出函數,使用“_stdcall標準調用extern"C"_declspec(dllexport)int_stdcallcount(intinit);int_stdcallcount(intinit)/count函數,使用參數i
11、nit初始化靜態的整形變量S,并使S自加1后返回該值staticintS=init;S+;returnS;)5) 按"F7進行編譯,得到Count.dll(在工程目錄下的Debug文件夾中).2. 用DllImport調用DLL中的count函數1) 翻開工程“Tzb,向“Form1窗體中添加一個按鈕.2) 改變按鈕的屬性:Name為"B2',Text為“用DllImport調用DLL中count函數,并將按鈕B1調整到適當大小,移到適當位置.3) 翻開"Form1.cs代碼視圖,使用關鍵字static和extern聲明方法"count,并使其具
12、有來自Count.dll的導出函數count的實現,代碼如下:DllImport("Count.dll")staticexternintcount(intinit);4) 在“Form1.cs設計視圖中雙擊按鈕B2,在“B2_Click方法體內添加如下代碼:MessageBox.Show("用DllImport調用DLL中的count函數,n傳入的實參為0,得到的結果是:"+count(0).ToString(),"挑戰杯");MessageBox.Show("用DllImport調用DLL中的count函數,n傳入的實參為
13、10,得到的結果是:"+count(10).ToString()+"n結果可不是想要的11哦!","挑戰杯");MessageBox.Show("所得結果說明:n用DllImport調用DLL中的非托管n函數是全局的、靜態的函數!","挑戰杯");5) 把Count.dll復制到工程"Tzb"的binDebug文件夾中,按"F5"運行該程序,并點擊按鈕B2,便彈出如下三個提示框:第1個提示框顯示的是調用“count(0)的結果,第2個提示框顯示的是調用“count(
14、10)的結果,由所得結果可以證實“用DllImport調用DLL中的非托管函數是全局的、靜態的函數.所以,有時候并不能到達我們目的,因此我們需要使用下面所介紹的方法:C時態調用DLL中的函數.3. C#動態調用DLL中的函數由于C#中使用DllImport是不能像動態load/unloadassembly那樣,所以只能借助API函數了.在kernel32.dll中,與動態庫調用有關的函數包括3:LoadLibrary(或MFC的AfxLoadLibrary),裝載動態庫.GetProcAddress,獲取要引入的函數,將符號名或標識號轉換為DLL內部地址.FreeLibrary(或MFC勺Af
15、xFreeLibrary),釋放動態鏈接庫.它們的原型分別是:HMODULELoadLibrary(LPCTSTRlpFileName);FARPROCGetProcAddress(HMODULEhModule,LPCWSTRlpProcName);BOOLFreeLibrary(HMODULEhModule);現在,我們可以用IntPtrhModule=LoadLibrary("Count.dll");來獲得Dll的句柄,用IntPtrfarProc=GetProcAddress(hModule,"_count4');來獲得函數的入口地址.但是,知道函數
16、的入口地址后,怎樣調用這個函數呢?由于在CM是沒有函數指針的,沒有像C+W樣的函數指針調用方式來調用函數,所以我們得借助其它方法.經過研究,發現我們可以通過結合使用System.Reflection.Emit及System.Reflection.Assembly里的類和函數到達我們的目的.為了以后使用方便及實現代碼的復用,我們可以編寫一個類.1) dld類的編寫:1. 翻開工程“Tzb,翻開類視圖,右擊“Tzb,選擇“添加->“類,類名設置為"dld",即dynamicloadingdll的每個單詞的開頭字母.2. 添加所需的命名空間及聲明參數傳遞方式枚舉:using
17、System.Runtime.InteropServices;/用DllImport需用此命名空間usingSystem.Reflection;/使用Assembly類需用此命名空間usingSystem.Reflection.Emit;/使用Generator需用此命名空間在"publicclassdld上面添加如下代碼聲明參數傳遞方式枚舉:/<summary>/參數傳遞方式枚舉,ByValue表示值傳遞,ByRef表示址傳遞/</summary>publicenumModePassByValue=0x0001,ByRef=0x00023. 聲明LoadLi
18、brary、GetProcAddress、FreeLibrary及私有變量hModule和farProc:/<summary>/原型是:HMODULELoadLibrary(LPCTSTRlpFileName);/</summary>/<paramname="lpFileName">DLL文件名</param>/<returns>函數庫模塊的句柄</returns>DllImport("kernel32.dll")staticexternIntPtrLoadLibrary(strin
19、glpFileName);/<summary>/原型是:FARPROCGetProcAddress(HMODULEhModule,LPCWSTRlpProcName);/</summary>/<paramname="hModule>包含需調用函數的函數庫模塊的句柄</param>/<paramname="lpProcName">調用函數的名稱</param>/<returns>函數指針</returns>DllImport("kernel32.dll"
20、;)staticexternIntPtrGetProcAddress(IntPtrhModule,stringlpProcName);/<summary>/原型是:BOOLFreeLibrary(HMODULEhModule);/</summary>/<paramname="hModule">需釋放的函數庫模塊的句柄</param>/<returns>是否已釋放指定的Dll</returns>DllImport("kernel32",EntryPoint="FreeLibr
21、ary",SetLastError=true)staticexternboolFreeLibrary(IntPtrhModule);/<summary>/Loadlibrary返回的函數庫模塊的句柄/</summary>privateIntPtrhModule=IntPtr.Zero;/<summary>/GetProcAddress返回的函數指針/</summary>privateIntPtrfarProc=IntPtr.Zero;4. 添加LoadDll方法,并為了調用時方便,重載了這個方法:/<summary>/裝載D
22、ll/</summary>/<paramname="lpFileName">DLL文件名</param>publicvoidLoadDll(stringIpFileName)(hModule=LoadLibrary(lpFileName);if(hModule=IntPtr.Zero)throw(newException("沒有找到:"+lpFileName+".");假設已有已裝載Dll的句柄,可以使用LoadDll方法的第二個版本:publicvoidLoadDll(IntPtrHMODULE)
23、(if(HMODULE=IntPtr.Zero)throw(newException("所傳入的函數庫模塊的句柄HMODUL助空.");hModule=HMODULE;5. 添加LoadFun方法,并為了調用時方便,也重載了這個方法,方法的具體代碼及注釋如下:/<summary>/獲得函數指針/</summary>/<paramname="lpProcName">調用函數的名稱</param>publicvoidLoadFun(stringlpProcName)/假設函數庫模塊的句柄為空,那么拋出異常if(hModule=IntPtr.Zero)throw(newException("函數庫模塊的句柄為空,請保證已進行LoadDll操作!");/取得函數指針farProc=GetProcAddress(hModule,lpProcName);/假設函數指
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年廠里廠里安全培訓考試試題及答案完整
- 25年公司項目部負責人安全培訓考試試題含答案【預熱題】
- 2024-2025工廠車間安全培訓考試試題(各地真題)
- 2025-2030中國智能水產品行業市場發展趨勢與前景展望戰略研究報告
- 2025-2030中國數碼沖印技術行業市場現狀供需分析及重點企業投資評估規劃分析研究報告
- 2025-2030中國拍攝行業發展現狀及前景趨勢與投資研究報告
- 2025-2030中國寵物行業市場發展分析及發展趨勢與投資前景預測報告
- 2025-2030中國女人用品行業市場發展現狀及競爭格局與投資前景研究報告
- 2025-2030中國動力輔助工具磨具行業市場發展趨勢與前景展望戰略研究報告
- 2025-2030中國克羅恩病的診斷和治療行業市場發展趨勢與前景展望戰略研究報告
- 新浙教版七年級上冊初中科學 第2節 質量的測量 教學課件
- 中華人民共和國招標投標法(PPT)
- 統編版四年級道德與法治下冊第8課《這些東西哪里來》精美課件(含視頻)
- 停車場應急預案
- 手術質量與安全分析報告模板
- 研究生在讀證明.docx
- 觀音庵收費站關于計重設備的管理和使用細則
- 卡農曲譜canon-in-D-鋼琴小提琴合奏-五線譜(共6頁)
- 常用藥物配伍禁忌表
- IATF16949:2016中文完整
- 2020年度希望之星英語大賽小低組看圖說話(圖文五篇
評論
0/150
提交評論