成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C#調用DLL函數方法(下)

開發 后端
本文繼續介紹了C#調用DLL函數方法。

本文的內容接著C#調用DLL函數方法(上)。

因為C#中使用DllImport是不能像動態load/unload assembly那樣,所以只能借助API函數了。在kernel32.dll中,與動態庫調用有關的函數包括[3]:

①LoadLibrary(或MFC 的AfxLoadLibrary),裝載動態庫。

②GetProcAddress,獲取要引入的函數,將符號名或標識號轉換為DLL內部地址。

③FreeLibrary(或MFC的AfxFreeLibrary),釋放動態鏈接庫。

它們的原型分別是:

HMODULE LoadLibrary(LPCTSTR lpFileName);

FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);

BOOL FreeLibrary(HMODULE hModule);

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

但是,知道函數的入口地址后,怎樣調用這個函數呢?因為在C#中是沒有函數指針的,沒有像C++那樣的函數指針調用方式來調用函數,所以我們得借助其它方法。經過研究,發現我們可以通過結合使用System.Reflection.Emit及System.Reflection.Assembly里的類和函數達到我們的目的。為了以后使用方便及實現代碼的復用,我們可以編寫一個類。

1) dld類的編寫:

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

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

  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”的上面,添加如下代碼聲明參數傳遞方式枚舉:

   

  1. /// < summary>   
  2.  
  3.     /// 參數傳遞方式枚舉,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 返回的函數庫模塊的句柄   
  28.  
  29.    
  30.  
  31.         /// < /summary>   
  32.  
  33.    
  34.  
  35.         private IntPtr hModule = IntPtr.Zero;  
  36.  
  37.    
  38.  
  39.         /// < summary>   
  40.  
  41.    
  42.  
  43.         /// GetProcAddress 返回的函數指針   
  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.         /// 獲得函數指針   
  98.  
  99.    
  100.  
  101.         /// < /summary>   
  102.  
  103.    
  104.  
  105.         /// < param name="lpProcName"> 調用函數的名稱 < /param>   
  106.  
  107.    
  108.  
  109.         public void LoadFun(string lpProcName)  
  110.  
  111.         { // 若函數庫模塊的句柄為空,則拋出異常   
  112.  
  113.    
  114.  
  115.             if (hModule == IntPtr.Zero)  
  116.  
  117.    
  118.  
  119.                 throw (new Exception(" 函數庫模塊的句柄為空 , 請確保已進行 LoadDll 操作 !"));  
  120.  
  121.    
  122.  
  123.             // 取得函數指針   
  124.  
  125.    
  126.  
  127.             farProc = GetProcAddress(hModule, lpProcName);  
  128.  
  129.    
  130.  
  131.             // 若函數指針,則拋出異常   
  132.  
  133.    
  134.  
  135.             if (farProc == IntPtr.Zero)  
  136.  
  137.    
  138.  
  139.                 throw (new Exception(" 沒有找到 :" + lpProcName + " 這個函數的入口點 "));  
  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.         /// 調用所設定的函數   
  188.  
  189.    
  190.  
  191.         /// < /summary>   
  192.  
  193.    
  194.  
  195.         /// < param name="ObjArray_Parameter"> 實參 < /param>   
  196.  
  197.    
  198.  
  199.         /// < param name="TypeArray_ParameterType"> 實參類型 < /param>   
  200.  
  201.    
  202.  
  203.         /// < param name="ModePassArray_Parameter"> 實參傳送方式 < /param>   
  204.  
  205.    
  206.  
  207.         /// < param name="Type_Return"> 返回類型 < /param>   
  208.  
  209.    
  210.  
  211.         /// < returns> 返回所調用函數的 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 個 if 是進行安全檢查 , 若不能通過 , 則拋出異常   
  222.  
  223.    
  224.  
  225.             if (hModule == IntPtr.Zero)  
  226.  
  227.    
  228.  
  229.                 throw (new Exception(" 函數庫模塊的句柄為空 , 請確保已進行 LoadDll 操作 !"));  
  230.  
  231.    
  232.  
  233.             if (farProc == IntPtr.Zero)  
  234.  
  235.    
  236.  
  237.                 throw (new Exception(" 函數指針為空 , 請確保已進行 LoadFun 操作 !"));  
  238.  
  239.    
  240.  
  241.             if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)  
  242.  
  243.    
  244.  
  245.                 throw (new Exception(" 參數個數及其傳遞方式的個數不匹配 ."));  
  246.  
  247.    
  248.  
  249.             // 下面是創建 MyAssemblyName 對象并設置其 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.             // 定義要調用的方法 , 方法名為“ MyFun ”,返回類型是“ Type_Return ”參數類型是“ TypeArray_ParameterType ”   
  274.  
  275.    
  276.  
  277.             MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("MyFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType);  
  278.  
  279.    
  280.  
  281.             // 獲取一個 ILGenerator ,用于發送所需的 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.             {// 用循環將參數依次壓入堆棧   
  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() + " 個參數沒有給定正確的傳遞方式 ."));  
  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);// 調用方法,并返回其值   
  408.  
  409.    
  410.  
  411.         }  
  412.  
  413.     }  
  414.  

2) dld類的使用:

1.打開項目“Test”,向“Form1”窗體中添加一個按鈕,和一個TestBox,Name改為txRet。視圖中雙擊按鈕,在“button1_Click”方法體上面添加代碼,創建一個dld類實例,并進行測試。具體如下:

  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[] { }; // 實參為0   
  22.  
  23.    
  24.  
  25.             Type[] ParameterTypes = new Type[] { }; // 實參類型為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為要測試的dll名稱,InitSDK為dll中的要測試的函數。

至此,C#調用DLL函數方法就介紹完了,希望對大家有所幫助。

【編輯推薦】

  1. C#自定義事件步步 通
  2. 如何在C#中使用存儲過程(SQL Server 2000)
  3. 存儲過程自動轉成C#源碼過程
  4. C#事件處理和自定義事件
  5. 通過C#反射特性查看自定義特性
責任編輯:book05 來源: csdn
相關推薦

2009-08-05 09:30:39

C#調用DLL函數

2009-08-07 17:22:36

C#調用dll導出函數

2009-08-03 12:57:27

C#調用DLL

2009-08-05 09:09:14

C#調用VC DLL接

2011-04-08 09:52:44

C++C#DLL

2009-07-31 14:54:48

dll函數C#導出

2009-07-31 17:28:35

C#語言調用DLL

2009-08-07 17:12:07

C# DLL函數

2009-08-05 17:06:39

ASP調用C# DLL

2009-08-05 16:41:36

C#調用VC dll

2009-09-02 17:16:01

冒泡排序

2009-08-05 15:04:14

C# dll注入

2009-08-05 16:49:42

C#中調用dll

2009-08-05 09:22:43

C#調用VC DLL

2009-08-31 16:33:28

C#調用Dispose

2009-08-31 18:05:14

C#調用WalkTre

2009-07-31 16:12:10

Windows APIC#

2009-08-25 10:59:00

C#調用函數顯示值

2009-08-03 13:34:57

C#調用Windows

2009-08-14 09:15:28

C#調用構造函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩中文字幕 | 黄色免费网址大全 | 中文字幕精品一区二区三区精品 | www.蜜桃av| 99亚洲视频 | 色噜噜亚洲男人的天堂 | 一级片av| 五月婷婷色 | 午夜免费福利影院 | 秋霞电影一区二区三区 | 在线欧美一区 | 天天干精品 | av大片在线观看 | 国产精品亚洲精品日韩已方 | 色婷婷一区二区三区四区 | 免费精品视频 | 日韩在线免费电影 | 国产黄色精品在线观看 | 国产精品视频久久 | 一级黄色网页 | 日日夜夜天天综合 | 免费日韩av | 欧美5区 | 成人网在线看 | 国产亚洲精品精品国产亚洲综合 | 99re在线免费视频 | 久久国产精品一区二区三区 | 久久国产精品视频 | 亚洲视频在线观看免费 | 国产美女一区二区 | 亚洲成人精品一区二区 | 国产操操操 | 在线看日韩 | 久久精品国产久精国产 | 一区二区三区av | 精品中文在线 | 麻豆视频国产在线观看 | 91精品久久久久久久久中文字幕 | 9191成人精品久久 | 欧美综合一区二区三区 | 精品乱码一区二区 |