C# 中如何动态调用非托管DLL(一)转载

隐藏行号 复制代码 这是一段程序代码。
  1. using System;
    
  2. using System.Collections.Generic;
    
  3. using System.Linq;
    
  4. using System.Text;
    
  5. using System.Runtime.InteropServices;
    
  6. using System.Reflection;
    
  7. using System.Reflection.Emit;
    
  8.  
  9. namespace IdeaSoft.ECEMonitor.Utils
    
  10. {
    
  11.     /// <summary> 
    
  12.     /// 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递 
    
  13.     /// </summary> 
    
  14.     public enum ModePass
    
  15.     {
    
  16.         ByValue = 0x0001,
    
  17.         ByRef = 0x0002
    
  18.     }
    
  19.  
  20.     public class DllLoader
    
  21.     {
    
  22.         /// <summary> 
    
  23.         /// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName); 
    
  24.         /// </summary> 
    
  25.         /// <param name="lpFileName">DLL 文件名 </param> 
    
  26.         /// <returns> 函数库模块的句柄 </returns> 
    
  27.         [DllImport("kernel32.dll")]
    
  28.         static extern IntPtr LoadLibrary(string lpFileName);
    
  29.  
  30.         /// <summary> 
    
  31.         /// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName); 
    
  32.         /// </summary> 
    
  33.         /// <param name="hModule"> 包含需调用函数的函数库模块的句柄 </param> 
    
  34.         /// <param name="lpProcName"> 调用函数的名称 </param> 
    
  35.         /// <returns> 函数指针 </returns> 
    
  36.         [DllImport("kernel32.dll")]
    
  37.         static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    
  38.  
  39.         /// <summary> 
    
  40.         /// 原型是 : BOOL FreeLibrary(HMODULE hModule); 
    
  41.         /// </summary> 
    
  42.         /// <param name="hModule"> 需释放的函数库模块的句柄 </param> 
    
  43.         /// <returns> 是否已释放指定的 Dll</returns> 
    
  44.         [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
    
  45.         static extern bool FreeLibrary(IntPtr hModule);
    
  46.  
  47.         /// <summary> 
    
  48.         /// Loadlibrary 返回的函数库模块的句柄 
    
  49.         /// </summary> 
    
  50.         private IntPtr hModule = IntPtr.Zero;
    
  51.         /// <summary> 
    
  52.         /// GetProcAddress 返回的函数指针 
    
  53.         /// </summary> 
    
  54.         private IntPtr farProc = IntPtr.Zero;
    
  55.  
  56.         /// <summary> 
    
  57.         /// 装载 Dll 
    
  58.         /// </summary> 
    
  59.         /// <param name="lpFileName">DLL 文件名 </param> 
    
  60.         public void LoadDll(string lpFileName)
    
  61.         {
    
  62.             hModule = LoadLibrary(lpFileName);
    
  63.             if (hModule == IntPtr.Zero)
    
  64.                 throw (new Exception(" 没有找到 :" + lpFileName + "."));
    
  65.         }
    
  66.  
  67.         /// <summary>
    
  68.         /// 若已有已装载Dll的句柄,可以使用LoadDll方法的第二个版本:
    
  69.         /// </summary>
    
  70.         /// <param name="HMODULE"></param>
    
  71.         public void LoadDll(IntPtr HMODULE)
    
  72.         {
    
  73.             if (HMODULE == IntPtr.Zero)
    
  74.                 throw (new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 ."));
    
  75.             hModule = HMODULE;
    
  76.         }
    
  77.  
  78.         /// <summary> 
    
  79.         /// 获得函数指针 
    
  80.         /// </summary> 
    
  81.         /// <param name="lpProcName"> 调用函数的名称 </param> 
    
  82.         public void LoadFun(string lpProcName)
    
  83.         {
    
  84.             // 若函数库模块的句柄为空,则抛出异常 
    
  85.             if (hModule == IntPtr.Zero)
    
  86.                 throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
    
  87.  
  88.             // 取得函数指针 
    
  89.             farProc = GetProcAddress(hModule, lpProcName);
    
  90.  
  91.             // 若函数指针,则抛出异常 
    
  92.             if (farProc == IntPtr.Zero)
    
  93.                 throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 "));
    
  94.  
  95.         }
    
  96.  
  97.         /// <summary> 
    
  98.         /// 获得函数指针 
    
  99.         /// </summary> 
    
  100.         /// <param name="lpFileName"> 包含需调用函数的 DLL 文件名 </param> 
    
  101.         /// <param name="lpProcName"> 调用函数的名称 </param> 
    
  102.         public void LoadFun(string lpFileName, string lpProcName)
    
  103.         {
    
  104.             // 取得函数库模块的句柄 
    
  105.             hModule = LoadLibrary(lpFileName);
    
  106.             // 若函数库模块的句柄为空,则抛出异常 
    
  107.             if (hModule == IntPtr.Zero)
    
  108.                 throw (new Exception(" 没有找到 :" + lpFileName + "."));
    
  109.  
  110.             // 取得函数指针 
    
  111.             farProc = GetProcAddress(hModule, lpProcName);
    
  112.  
  113.             // 若函数指针,则抛出异常 
    
  114.             if (farProc == IntPtr.Zero)
    
  115.                 throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 "));
    
  116.         }
    
  117.  
  118.         /// <summary> 
    
  119.         /// 卸载 Dll 
    
  120.         /// </summary> 
    
  121.         public void UnLoadDll()
    
  122.         {
    
  123.             FreeLibrary(hModule);
    
  124.             hModule = IntPtr.Zero;
    
  125.             farProc = IntPtr.Zero;
    
  126.         }
    
  127.  
  128.         /// <summary> 
    
  129.         /// 调用所设定的函数 
    
  130.         /// </summary> 
    
  131.         /// <param name="ObjArray_Parameter"> 实参 </param> 
    
  132.         /// <param name="TypeArray_ParameterType"> 实参类型 </param> 
    
  133.         /// <param name="ModePassArray_Parameter"> 实参传送方式 </param> 
    
  134.         /// <param name="Type_Return"> 返回类型 </param> 
    
  135.         /// <returns> 返回所调用函数的 object</returns> 
    
  136. 
    
  137.         public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
    
  138.         {
    
  139.             // 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 
    
  140.             if (hModule == IntPtr.Zero)
    
  141.                 throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
    
  142.  
  143.             if (farProc == IntPtr.Zero)
    
  144.                 throw (new Exception(" 函数指针为空 , 请确保已进行 LoadFun 操作 !"));
    
  145.  
  146.             if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)
    
  147.                 throw (new Exception(" 参数个数及其传递方式的个数不匹配 ."));
    
  148.  
  149.             // 下面是创建 MyAssemblyName 对象并设置其 Name 属性 
    
  150.             AssemblyName MyAssemblyName = new AssemblyName();
    
  151.             MyAssemblyName.Name = "InvokeFun";
    
  152.  
  153.             // 生成单模块配件 
    
  154.             AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run);
    
  155.             ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll");
    
  156.  
  157.             // 定义要调用的方法 , 方法名为“ MyFun ”,返回类型是“ Type_Return ”参数类型是“ TypeArray_ParameterType ” 
    
  158.             MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("MyFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType);
    
  159.             
    
  160.             // 获取一个 ILGenerator ,用于发送所需的 IL 
    
  161.             ILGenerator IL = MyMethodBuilder.GetILGenerator();
    
  162.  
  163.             int i;
    
  164.             for (i = 0; i < ObjArray_Parameter.Length; i++)
    
  165.             {
    
  166.                 // 用循环将参数依次压入堆栈 
    
  167.                 switch (ModePassArray_Parameter[i])
    
  168.                 {
    
  169.                     case ModePass.ByValue:
    
  170.                         IL.Emit(OpCodes.Ldarg, i);
    
  171.                         break;
    
  172.                     case ModePass.ByRef:
    
  173.                         IL.Emit(OpCodes.Ldarga, i);
    
  174.                         break;
    
  175.                     default:
    
  176.                         throw (new Exception(" 第 " + (i + 1).ToString() + " 个参数没有给定正确的传递方式 ."));
    
  177.                 }
    
  178.             }
    
  179.  
  180.             if (IntPtr.Size == 4)
    
  181.             {
    
  182.                 // 判断处理器类型 
    
  183.                 IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
    
  184.             }
    
  185.             else if (IntPtr.Size == 8)
    
  186.             {
    
  187.                 IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
    
  188.             }
    
  189.             else
    
  190.             {
    
  191.                 throw new PlatformNotSupportedException();
    
  192.             }
    
  193.             IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_ParameterType);
    
  194.             IL.Emit(OpCodes.Ret); // 返回值 
    
  195.             MyModuleBuilder.CreateGlobalFunctions();
    
  196.  
  197.             // 取得方法信息 
    
  198.             MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun");
    
  199.             return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值 
    
  200.         }
    
  201.  
  202.  
  203.         /// <summary> 
    
  204.         /// 调用所设定的函数 
    
  205.         /// </summary> 
    
  206.         /// <param name="IntPtr_Function"> 函数指针 </param> 
    
  207.         /// <param name="ObjArray_Parameter"> 实参 </param> 
    
  208.         /// <param name="TypeArray_ParameterType"> 实参类型 </param> 
    
  209.         /// <param name="ModePassArray_Parameter"> 实参传送方式 </param> 
    
  210.         /// <param name="Type_Return"> 返回类型 </param> 
    
  211.         /// <returns> 返回所调用函数的 object</returns> 
    
  212.         public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return)
    
  213.         {
    
  214.             // 下面 2 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 
    
  215.             if (hModule == IntPtr.Zero)
    
  216.                 throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
    
  217.  
  218.             if (IntPtr_Function == IntPtr.Zero)
    
  219.                 throw (new Exception(" 函数指针 IntPtr_Function 为空 !"));
    
  220.  
  221.             farProc = IntPtr_Function;
    
  222.             return Invoke(ObjArray_Parameter, TypeArray_ParameterType, ModePassArray_Parameter, Type_Return);
    
  223.  
  224.         }
    
  225.  
  226.     }
    
  227. }
    

转载于:https://www.cnblogs.com/zpzhang/archive/2009/09/01/1557800.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值