今天就跟大家聊聊有關(guān)C#中怎么調(diào)用DLL函數(shù),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、做網(wǎng)站、長汀網(wǎng)絡(luò)推廣、成都微信小程序、長汀網(wǎng)絡(luò)營銷、長汀企業(yè)策劃、長汀品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供長汀建站搭建服務(wù),24小時服務(wù)熱線:13518219792,官方網(wǎng)址:www.rwnh.cn
因為C#中使用DllImport是不能像動態(tài)load/unload assembly那樣,所以只能借助API函數(shù)了。在kernel32.dll中,與動態(tài)庫調(diào)用有關(guān)的函數(shù)包括[3]:
①LoadLibrary(或MFC 的AfxLoadLibrary),裝載動態(tài)庫。
②GetProcAddress,獲取要引入的函數(shù),將符號名或標識號轉(zhuǎn)換為DLL內(nèi)部地址。
③FreeLibrary(或MFC的AfxFreeLibrary),釋放動態(tài)鏈接庫。
它們的原型分別是:
HMODULE LoadLibrary(LPCTSTR lpFileName);
FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
BOOL FreeLibrary(HMODULE hModule);
現(xiàn)在,我們可以用IntPtr hModule=LoadLibrary(“Count.dll”);來獲得Dll的句柄,用IntPtr farProc=GetProcAddress(hModule,”_count@4”);來獲得函數(shù)的入口地址。
但是,知道函數(shù)的入口地址后,怎樣調(diào)用這個函數(shù)呢?因為在C#中是沒有函數(shù)指針的,沒有像C++那樣的函數(shù)指針調(diào)用方式來調(diào)用函數(shù),所以我們得借助其它方法。經(jīng)過研究,發(fā)現(xiàn)我們可以通過結(jié)合使用System.Reflection.Emit及System.Reflection.Assembly里的類和函數(shù)達到我們的目的。為了以后使用方便及實現(xiàn)代碼的復(fù)用,我們可以編寫一個類。
1) dld類的編寫:
1.打開項目“Test”,打開類視圖,右擊“Tzb”,選擇“添加”-->“類”,類名設(shè)置為“dld”,即dynamic loading dll 的每個單詞的開頭字母。
2.添加所需的命名空間及聲明參數(shù)傳遞方式枚舉:
using System.Runtime.InteropServices; // 用DllImport 需用此命名空間 using System.Reflection; // 使用Assembly 類需用此命名空間 using System.Reflection.Emit; // 使用ILGenerator 需用此命名空間
3. 在namespace test中,“public class dld”的上面,添加如下代碼聲明參數(shù)傳遞方式枚舉:
/// < summary> /// 參數(shù)傳遞方式枚舉,ByValue 表示值傳遞,ByRef 表示址傳遞 /// < /summary> public enum ModePass { ByValue = 0x0001, ByRef = 0x0002 }
4、在public class DLD中,添加如下代碼:
public class DLD { [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProceName); [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)] public static extern bool FreeLibrary(IntPtr hModule); /// < summary> /// Loadlibrary 返回的函數(shù)庫模塊的句柄 /// < /summary> private IntPtr hModule = IntPtr.Zero; /// < summary> /// GetProcAddress 返回的函數(shù)指針 /// < /summary> private IntPtr farProc = IntPtr.Zero; /// < summary> /// 裝載 Dll /// < /summary> /// < param name="lpFileName">DLL 文件名 < /param> public void LoadDll(string lpFileName) { hModule = LoadLibrary(lpFileName); if (hModule == IntPtr.Zero) throw (new Exception(" 沒有找到 :" + lpFileName + ".")); } /// < summary> /// 獲得函數(shù)指針 /// < /summary> /// < param name="lpProcName"> 調(diào)用函數(shù)的名稱 < /param> public void LoadFun(string lpProcName) { // 若函數(shù)庫模塊的句柄為空,則拋出異常 if (hModule == IntPtr.Zero) throw (new Exception(" 函數(shù)庫模塊的句柄為空 , 請確保已進行 LoadDll 操作 !")); // 取得函數(shù)指針 farProc = GetProcAddress(hModule, lpProcName); // 若函數(shù)指針,則拋出異常 if (farProc == IntPtr.Zero) throw (new Exception(" 沒有找到 :" + lpProcName + " 這個函數(shù)的入口點 ")); } /// < summary> /// 卸載 Dll /// < /summary> public void UnLoadDll() { FreeLibrary(hModule); hModule = IntPtr.Zero; farProc = IntPtr.Zero; } /// < summary> /// 調(diào)用所設(shè)定的函數(shù) /// < /summary> /// < param name="ObjArray_Parameter"> 實參 < /param> /// < param name="TypeArray_ParameterType"> 實參類型 < /param> /// < param name="ModePassArray_Parameter"> 實參傳送方式 < /param> /// < param name="Type_Return"> 返回類型 < /param> /// < returns> 返回所調(diào)用函數(shù)的 object< /returns> public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return) { // 下面 3 個 if 是進行安全檢查 , 若不能通過 , 則拋出異常 if (hModule == IntPtr.Zero) throw (new Exception(" 函數(shù)庫模塊的句柄為空 , 請確保已進行 LoadDll 操作 !")); if (farProc == IntPtr.Zero) throw (new Exception(" 函數(shù)指針為空 , 請確保已進行 LoadFun 操作 !")); if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length) throw (new Exception(" 參數(shù)個數(shù)及其傳遞方式的個數(shù)不匹配 .")); // 下面是創(chuàng)建 MyAssemblyName 對象并設(shè)置其 Name 屬性 AssemblyName MyAssemblyName = new AssemblyName(); MyAssemblyName.Name = "InvokeFun"; // 生成單模塊配件 AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run); ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll"); // 定義要調(diào)用的方法 , 方法名為“ MyFun ”,返回類型是“ Type_Return ”參數(shù)類型是“ TypeArray_ParameterType ” MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("MyFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType); // 獲取一個 ILGenerator ,用于發(fā)送所需的 IL ILGenerator IL = MyMethodBuilder.GetILGenerator(); int i; for (i = 0; i < ObjArray_Parameter.Length; i++) {// 用循環(huán)將參數(shù)依次壓入堆棧 switch (ModePassArray_Parameter[i]) { case ModePass.ByValue: IL.Emit(OpCodes.Ldarg, i); break; case ModePass.ByRef: IL.Emit(OpCodes.Ldarga, i); break; default: throw (new Exception(" 第 " + (i + 1).ToString() + " 個參數(shù)沒有給定正確的傳遞方式 .")); } } if (IntPtr.Size == 4) {// 判斷處理器類型 IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32()); } else if (IntPtr.Size == 8) { IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64()); } else { throw new PlatformNotSupportedException(); } IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_ParameterType); IL.Emit(OpCodes.Ret); // 返回值 MyModuleBuilder.CreateGlobalFunctions(); // 取得方法信息 MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun"); return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 調(diào)用方法,并返回其值 } }
2) dld類的使用:
1.打開項目“Test”,向“Form1”窗體中添加一個按鈕,和一個TestBox,Name改為txRet。視圖中雙擊按鈕,在“button1_Click”方法體上面添加代碼,創(chuàng)建一個dld類實例,并進行測試。具體如下:
private void button1_Click(object sender, EventArgs e) { int ret = 0; dld myDLD = new dld(); myDLD.LoadDll("xxx.dll"); myDLD.LoadFun("InitSDK"); object[] Parameters = new object[] { }; // 實參為0 Type[] ParameterTypes = new Type[] { }; // 實參類型為int ModePass[] themode = new ModePass[] { }; // 傳送方式為值傳 Type Type_Return = typeof(int); // 返回類型為int ret = (int)myDLD.Invoke(Parameters, ParameterTypes, themode, Type_Return); txRet.Text = ret.ToString(); if (ret != 1) { MessageBox.Show("InitSDK failed !"); } if (ret == 1) { MessageBox.Show("InitSDK Sucessed !"); } }
其中,xxx為要測試的dll名稱,InitSDK為dll中的要測試的函數(shù)。
看完上述內(nèi)容,你們對C#中怎么調(diào)用DLL函數(shù)有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
當前題目:C#中怎么調(diào)用DLL函數(shù)
當前URL:http://www.rwnh.cn/article40/jiesho.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、定制開發(fā)、商城網(wǎng)站、網(wǎng)站收錄、外貿(mào)網(wǎng)站建設(shè)、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)