自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C#調(diào)用DLL函數(shù)方法(下)

開發(fā) 后端
本文繼續(xù)介紹了C#調(diào)用DLL函數(shù)方法。

本文的內(nèi)容接著C#調(diào)用DLL函數(shù)方法(上)。

因?yàn)镃#中使用DllImport是不能像動(dòng)態(tài)load/unload assembly那樣,所以只能借助API函數(shù)了。在kernel32.dll中,與動(dòng)態(tài)庫(kù)調(diào)用有關(guān)的函數(shù)包括[3]:

①LoadLibrary(或MFC 的AfxLoadLibrary),裝載動(dòng)態(tài)庫(kù)。

②GetProcAddress,獲取要引入的函數(shù),將符號(hào)名或標(biāo)識(shí)號(hào)轉(zhuǎn)換為DLL內(nèi)部地址。

③FreeLibrary(或MFC的AfxFreeLibrary),釋放動(dòng)態(tài)鏈接庫(kù)。

它們的原型分別是:

HMODULE LoadLibrary(LPCTSTR lpFileName);

FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);

BOOL FreeLibrary(HMODULE hModule);

現(xiàn)在,我們可以用IntPtr hModule=LoadLibrary(“Count.dll”);來(lái)獲得Dll的句柄,用IntPtr farProc=GetProcAddress(hModule,”_count@4”);來(lái)獲得函數(shù)的入口地址。

但是,知道函數(shù)的入口地址后,怎樣調(diào)用這個(gè)函數(shù)呢?因?yàn)樵贑#中是沒有函數(shù)指針的,沒有像C++那樣的函數(shù)指針調(diào)用方式來(lái)調(diào)用函數(shù),所以我們得借助其它方法。經(jīng)過(guò)研究,發(fā)現(xiàn)我們可以通過(guò)結(jié)合使用System.Reflection.Emit及System.Reflection.Assembly里的類和函數(shù)達(dá)到我們的目的。為了以后使用方便及實(shí)現(xiàn)代碼的復(fù)用,我們可以編寫一個(gè)類。

1) dld類的編寫:

1.打開項(xiàng)目“Test”,打開類視圖,右擊“Tzb”,選擇“添加”-->“類”,類名設(shè)置為“dld”,即dynamic loading dll 的每個(gè)單詞的開頭字母。

2.添加所需的命名空間及聲明參數(shù)傳遞方式枚舉:

  1. using System.Runtime.InteropServices; // 用DllImport 需用此命名空間  
  2.  
  3. using System.Reflection; // 使用Assembly 類需用此命名空間  
  4.  
  5. using System.Reflection.Emit; // 使用ILGenerator 需用此命名空間  

3. 在namespace test中,“public class dld”的上面,添加如下代碼聲明參數(shù)傳遞方式枚舉:

   

  1. /// < summary>   
  2.  
  3.     /// 參數(shù)傳遞方式枚舉,ByValue 表示值傳遞,ByRef 表示址傳遞  
  4.  
  5.     /// < /summary>   
  6.  
  7.     public enum ModePass  
  8.  
  9.     {  
  10.  
  11.         ByValue = 0x0001,  
  12.  
  13.         ByRef = 0x0002  
  14.  
  15. }  
  16.  

4、在public class DLD中,添加如下代碼:

   

  1. public class DLD  
  2.  
  3.     {  
  4.  
  5.         [DllImport("kernel32.dll")]  
  6.  
  7.         public static extern IntPtr LoadLibrary(string lpFileName);  
  8.  
  9.    
  10.  
  11.         [DllImport("kernel32.dll")]  
  12.  
  13.         public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProceName);  
  14.  
  15.    
  16.  
  17.         [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]  
  18.  
  19.         public static extern bool FreeLibrary(IntPtr hModule);  
  20.  
  21.    
  22.  
  23.         /// < summary>   
  24.  
  25.    
  26.  
  27.         /// Loadlibrary 返回的函數(shù)庫(kù)模塊的句柄   
  28.  
  29.    
  30.  
  31.         /// < /summary>   
  32.  
  33.    
  34.  
  35.         private IntPtr hModule = IntPtr.Zero;  
  36.  
  37.    
  38.  
  39.         /// < summary>   
  40.  
  41.    
  42.  
  43.         /// GetProcAddress 返回的函數(shù)指針   
  44.  
  45.    
  46.  
  47.         /// < /summary>   
  48.  
  49.    
  50.  
  51.         private IntPtr farProc = IntPtr.Zero;  
  52.  
  53.    
  54.  
  55.         /// < summary>   
  56.  
  57.    
  58.  
  59.         /// 裝載 Dll   
  60.  
  61.    
  62.  
  63.         /// < /summary>   
  64.  
  65.    
  66.  
  67.         /// < param name="lpFileName">DLL 文件名 < /param>   
  68.  
  69.    
  70.  
  71.         public void LoadDll(string lpFileName)  
  72.  
  73.         {  
  74.  
  75.    
  76.  
  77.             hModule = LoadLibrary(lpFileName);  
  78.  
  79.    
  80.  
  81.             if (hModule == IntPtr.Zero)  
  82.  
  83.    
  84.  
  85.                 throw (new Exception(" 沒有找到 :" + lpFileName + "."));  
  86.  
  87.         }  
  88.  
  89.    
  90.  
  91.    
  92.  
  93.         /// < summary>   
  94.  
  95.    
  96.  
  97.         /// 獲得函數(shù)指針   
  98.  
  99.    
  100.  
  101.         /// < /summary>   
  102.  
  103.    
  104.  
  105.         /// < param name="lpProcName"> 調(diào)用函數(shù)的名稱 < /param>   
  106.  
  107.    
  108.  
  109.         public void LoadFun(string lpProcName)  
  110.  
  111.         { // 若函數(shù)庫(kù)模塊的句柄為空,則拋出異常   
  112.  
  113.    
  114.  
  115.             if (hModule == IntPtr.Zero)  
  116.  
  117.    
  118.  
  119.                 throw (new Exception(" 函數(shù)庫(kù)模塊的句柄為空 , 請(qǐng)確保已進(jìn)行 LoadDll 操作 !"));  
  120.  
  121.    
  122.  
  123.             // 取得函數(shù)指針   
  124.  
  125.    
  126.  
  127.             farProc = GetProcAddress(hModule, lpProcName);  
  128.  
  129.    
  130.  
  131.             // 若函數(shù)指針,則拋出異常   
  132.  
  133.    
  134.  
  135.             if (farProc == IntPtr.Zero)  
  136.  
  137.    
  138.  
  139.                 throw (new Exception(" 沒有找到 :" + lpProcName + " 這個(gè)函數(shù)的入口點(diǎn) "));  
  140.  
  141.    
  142.  
  143.         }  
  144.  
  145.    
  146.  
  147.         /// < summary>   
  148.  
  149.    
  150.  
  151.         /// 卸載 Dll   
  152.  
  153.    
  154.  
  155.         /// < /summary>   
  156.  
  157.    
  158.  
  159.         public void UnLoadDll()  
  160.  
  161.         {  
  162.  
  163.    
  164.  
  165.             FreeLibrary(hModule);  
  166.  
  167.    
  168.  
  169.             hModule = IntPtr.Zero;  
  170.  
  171.    
  172.  
  173.             farProc = IntPtr.Zero;  
  174.  
  175.    
  176.  
  177.         }  
  178.  
  179.    
  180.  
  181.    
  182.  
  183.         /// < summary>   
  184.  
  185.    
  186.  
  187.         /// 調(diào)用所設(shè)定的函數(shù)   
  188.  
  189.    
  190.  
  191.         /// < /summary>   
  192.  
  193.    
  194.  
  195.         /// < param name="ObjArray_Parameter"> 實(shí)參 < /param>   
  196.  
  197.    
  198.  
  199.         /// < param name="TypeArray_ParameterType"> 實(shí)參類型 < /param>   
  200.  
  201.    
  202.  
  203.         /// < param name="ModePassArray_Parameter"> 實(shí)參傳送方式 < /param>   
  204.  
  205.    
  206.  
  207.         /// < param name="Type_Return"> 返回類型 < /param>   
  208.  
  209.    
  210.  
  211.         /// < returns> 返回所調(diào)用函數(shù)的 object< /returns>   
  212.  
  213.    
  214.  
  215.         public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)  
  216.  
  217.         {  
  218.  
  219.    
  220.  
  221.             // 下面 3 個(gè) if 是進(jìn)行安全檢查 , 若不能通過(guò) , 則拋出異常   
  222.  
  223.    
  224.  
  225.             if (hModule == IntPtr.Zero)  
  226.  
  227.    
  228.  
  229.                 throw (new Exception(" 函數(shù)庫(kù)模塊的句柄為空 , 請(qǐng)確保已進(jìn)行 LoadDll 操作 !"));  
  230.  
  231.    
  232.  
  233.             if (farProc == IntPtr.Zero)  
  234.  
  235.    
  236.  
  237.                 throw (new Exception(" 函數(shù)指針為空 , 請(qǐng)確保已進(jìn)行 LoadFun 操作 !"));  
  238.  
  239.    
  240.  
  241.             if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)  
  242.  
  243.    
  244.  
  245.                 throw (new Exception(" 參數(shù)個(gè)數(shù)及其傳遞方式的個(gè)數(shù)不匹配 ."));  
  246.  
  247.    
  248.  
  249.             // 下面是創(chuàng)建 MyAssemblyName 對(duì)象并設(shè)置其 Name 屬性   
  250.  
  251.    
  252.  
  253.             AssemblyName MyAssemblyName = new AssemblyName();  
  254.  
  255.    
  256.  
  257.             MyAssemblyName.Name = "InvokeFun";  
  258.  
  259.    
  260.  
  261.             // 生成單模塊配件   
  262.  
  263.    
  264.  
  265.             AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run);  
  266.  
  267.    
  268.  
  269.             ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll");  
  270.  
  271.    
  272.  
  273.             // 定義要調(diào)用的方法 , 方法名為“ MyFun ”,返回類型是“ Type_Return ”參數(shù)類型是“ TypeArray_ParameterType ”   
  274.  
  275.    
  276.  
  277.             MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("MyFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType);  
  278.  
  279.    
  280.  
  281.             // 獲取一個(gè) ILGenerator ,用于發(fā)送所需的 IL   
  282.  
  283.    
  284.  
  285.             ILGenerator IL = MyMethodBuilder.GetILGenerator();  
  286.  
  287.    
  288.  
  289.             int i;  
  290.  
  291.    
  292.  
  293.             for (i = 0; i <  ObjArray_Parameter.Length; i++)  
  294.  
  295.             {// 用循環(huán)將參數(shù)依次壓入堆棧   
  296.  
  297.    
  298.  
  299.                 switch (ModePassArray_Parameter[i])  
  300.  
  301.                 {  
  302.  
  303.    
  304.  
  305.                     case ModePass.ByValue:  
  306.  
  307.    
  308.  
  309.                         IL.Emit(OpCodes.Ldarg, i);  
  310.  
  311.    
  312.  
  313.                         break;  
  314.  
  315.    
  316.  
  317.                     case ModePass.ByRef:  
  318.  
  319.    
  320.  
  321.                         IL.Emit(OpCodes.Ldarga, i);  
  322.  
  323.    
  324.  
  325.                         break;  
  326.  
  327.    
  328.  
  329.                     default:  
  330.  
  331.    
  332.  
  333.                         throw (new Exception(" 第 " + (i + 1).ToString() + " 個(gè)參數(shù)沒有給定正確的傳遞方式 ."));  
  334.  
  335.    
  336.  
  337.                 }  
  338.  
  339.    
  340.  
  341.             }  
  342.  
  343.    
  344.  
  345.             if (IntPtr.Size == 4)  
  346.  
  347.             {// 判斷處理器類型   
  348.  
  349.    
  350.  
  351.                 IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());  
  352.  
  353.    
  354.  
  355.             }  
  356.  
  357.    
  358.  
  359.             else if (IntPtr.Size == 8)  
  360.  
  361.             {  
  362.  
  363.    
  364.  
  365.                 IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());  
  366.  
  367.    
  368.  
  369.             }  
  370.  
  371.    
  372.  
  373.             else 
  374.  
  375.             {  
  376.  
  377.    
  378.  
  379.                 throw new PlatformNotSupportedException();  
  380.  
  381.    
  382.  
  383.             }  
  384.  
  385.    
  386.  
  387.             IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_ParameterType);  
  388.  
  389.    
  390.  
  391.             IL.Emit(OpCodes.Ret); // 返回值   
  392.  
  393.    
  394.  
  395.             MyModuleBuilder.CreateGlobalFunctions();  
  396.  
  397.    
  398.  
  399.             // 取得方法信息   
  400.  
  401.    
  402.  
  403.             MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun");  
  404.  
  405.    
  406.  
  407.             return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 調(diào)用方法,并返回其值   
  408.  
  409.    
  410.  
  411.         }  
  412.  
  413.     }  
  414.  

2) dld類的使用:

1.打開項(xiàng)目“Test”,向“Form1”窗體中添加一個(gè)按鈕,和一個(gè)TestBox,Name改為txRet。視圖中雙擊按鈕,在“button1_Click”方法體上面添加代碼,創(chuàng)建一個(gè)dld類實(shí)例,并進(jìn)行測(cè)試。具體如下:

  1. private void button1_Click(object sender, EventArgs e)  
  2.  
  3.         {  
  4.  
  5.    
  6.  
  7.             int ret = 0;  
  8.  
  9.             dld myDLD = new dld();  
  10.  
  11.    
  12.  
  13.             myDLD.LoadDll("xxx.dll");  
  14.  
  15.    
  16.  
  17.             myDLD.LoadFun("InitSDK");  
  18.  
  19.    
  20.  
  21.             object[] Parameters = new object[] { }; // 實(shí)參為0   
  22.  
  23.    
  24.  
  25.             Type[] ParameterTypes = new Type[] { }; // 實(shí)參類型為int   
  26.  
  27.    
  28.  
  29.             ModePass[] themode = new ModePass[] { }; // 傳送方式為值傳  
  30.  
  31.    
  32.  
  33.             Type Type_Return = typeof(int); // 返回類型為int  
  34.  
  35.    
  36.  
  37.             ret = (int)myDLD.Invoke(Parameters, ParameterTypes, themode, Type_Return);  
  38.  
  39.             txRet.Text = ret.ToString();  
  40.  
  41.             if (ret != 1)  
  42.  
  43.             {  
  44.  
  45.                 MessageBox.Show("InitSDK failed !");  
  46.  
  47.             }  
  48.  
  49.             if (ret == 1)  
  50.  
  51.             {  
  52.  
  53.                 MessageBox.Show("InitSDK Sucessed !");  
  54.  
  55.             }  
  56.  
  57.         }  
  58.  

其中,xxx為要測(cè)試的dll名稱,InitSDK為dll中的要測(cè)試的函數(shù)。

至此,C#調(diào)用DLL函數(shù)方法就介紹完了,希望對(duì)大家有所幫助。

【編輯推薦】

  1. C#自定義事件步步 通
  2. 如何在C#中使用存儲(chǔ)過(guò)程(SQL Server 2000)
  3. 存儲(chǔ)過(guò)程自動(dòng)轉(zhuǎn)成C#源碼過(guò)程
  4. C#事件處理和自定義事件
  5. 通過(guò)C#反射特性查看自定義特性
責(zé)任編輯:book05 來(lái)源: csdn
相關(guān)推薦

2009-08-05 09:30:39

C#調(diào)用DLL函數(shù)

2009-08-07 17:22:36

C#調(diào)用dll導(dǎo)出函數(shù)

2009-08-03 12:57:27

C#調(diào)用DLL

2009-08-05 09:09:14

C#調(diào)用VC DLL接

2011-04-08 09:52:44

C++C#DLL

2009-07-31 14:54:48

dll函數(shù)C#導(dǎo)出

2009-07-31 17:28:35

C#語(yǔ)言調(diào)用DLL

2009-08-07 17:12:07

C# DLL函數(shù)

2009-08-05 17:06:39

ASP調(diào)用C# DLL

2009-08-05 16:41:36

C#調(diào)用VC dll

2009-09-02 17:16:01

冒泡排序

2009-08-05 15:04:14

C# dll注入

2009-08-05 16:49:42

C#中調(diào)用dll

2009-08-05 09:22:43

C#調(diào)用VC DLL

2009-08-31 18:05:14

C#調(diào)用WalkTre

2009-08-31 16:33:28

C#調(diào)用Dispose

2009-08-25 10:59:00

C#調(diào)用函數(shù)顯示值

2009-07-31 16:12:10

Windows APIC#

2009-08-03 13:34:57

C#調(diào)用Windows

2009-08-14 09:15:28

C#調(diào)用構(gòu)造函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)