C#动态调用系统DLL函数的类(改进版)

http://blog.csdn.net/KAMILLE/archive/2008/01/15/2045459.aspx

几个月前写的版本,使用反射性能不够好,而且使用不够方便。这个版本使用接口定义,性能接近系统的DllImport。支持.net1.0。(如果是.net2.0可以使用Delegate转换函数指针)

  1. using System;
  2. using System.Reflection;
  3. using System.Reflection.Emit;
  4. using System.Runtime.InteropServices;
  5. public class DllImporter
  6. {
  7.     [DllImport("Kernel32.dll")]
  8.     static extern IntPtr LoadLibrary(string lpFileName);
  9.     [DllImport("Kernel32.dll")]
  10.     static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
  11.     [DllImport("Kernel32.dll")]
  12.     static extern bool FreeLibrary(IntPtr hModule);
  13.     public static object Create(string dllFile, Type interfaceType)
  14.     {
  15.         //检查参数
  16.         if (dllFile == nullthrow new ArgumentNullException();
  17.         if (interfaceType.IsInterface == falsethrow new ArgumentException();
  18.         //函数指针( 这里其实要释放的,偷懒:P )
  19.         IntPtr libPtr = LoadLibrary(dllFile);
  20.         if (libPtr == IntPtr.Zero) throw new DllNotFoundException(dllFile);
  21.         //创建模块
  22.         AssemblyName assemblyName = new AssemblyName();
  23.         assemblyName.Name = "DynamicAssembly";
  24.         AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  25.         ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
  26.         //创建类型
  27.         TypeBuilder type = moduleBuilder.DefineType("DynamicType", TypeAttributes.Class, typeof(Object), new Type[] { interfaceType });
  28.         //创建方法
  29.         MethodInfo[] methods = interfaceType.GetMethods();
  30.         foreach (MethodInfo method in methods)
  31.         {
  32.             IntPtr procPtr = GetProcAddress(libPtr, method.Name);
  33.             if (procPtr == IntPtr.Zero) throw new EntryPointNotFoundException(method.Name);
  34.             MethodAttributes attribute = method.Attributes & ~(MethodAttributes.Abstract);
  35.             Type returnType = method.ReturnType;
  36.             ParameterInfo[] parameters = method.GetParameters();
  37.             Type[] argumentsType = new Type[parameters.Length];
  38.             for (int i = 0; i < parameters.Length; i++)
  39.                 argumentsType[i] = parameters[i].ParameterType;
  40.             MethodBuilder methodBuilder = type.DefineMethod(method.Name, attribute, returnType, argumentsType);
  41.             ILGenerator ilGen = methodBuilder.GetILGenerator();
  42.             for (int i = 0; i < argumentsType.Length; i++)
  43.                 ilGen.Emit(OpCodes.Ldarg, i + 1);   //注意这里从1开始,0是this
  44.             if (IntPtr.Size == 4) ilGen.Emit(OpCodes.Ldc_I4, (int)procPtr);
  45.             else if (IntPtr.Size == 8) ilGen.Emit(OpCodes.Ldc_I8, (long)procPtr);
  46.             ilGen.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, returnType, argumentsType);
  47.             ilGen.Emit(OpCodes.Ret);
  48.             //显式接口方法需要定义 Override,而普通实现不需要。     
  49.             type.DefineMethodOverride(methodBuilder, method);
  50.         }
  51.         //FreeLibrary(libPtr);
  52.         //创建类型
  53.         return Activator.CreateInstance(type.CreateType());
  54.     }
  55. }
  56. public class Test
  57. {
  58.     public interface Iuser32
  59.     {
  60.         IntPtr GetDC(IntPtr hWnd);
  61.         int ReleaseDC(IntPtr hWnd, IntPtr hDC);
  62.     }
  63.     public interface Igdi32
  64.     {
  65.         bool TextOutA(IntPtr hdc, int nXStart, int nYStart, string lpString, int cbString);
  66.         uint SetTextColor(IntPtr hdc, uint crColor);
  67.     }
  68.     static void Main(string[] args)
  69.     {
  70.         Iuser32 user32 = DllImporter.Create("user32.dll"typeof(Iuser32)) as Iuser32;
  71.         Igdi32 gdi32 = DllImporter.Create("gdi32.dll"typeof(Igdi32)) as Igdi32;
  72.         IntPtr dc = user32.GetDC(IntPtr.Zero);
  73.         gdi32.SetTextColor(dc, 0xff);
  74.         int x = 0; int y = 0; int sx = 1; int sy = 1;
  75.         for (int i = 0; i < 10000; i++)
  76.         {
  77.             if (x > 1024 || x < 0) sx *= -1;
  78.             if (y > 768 || y < 0) sy *= -1;
  79.             x += sx;
  80.             y += sy;
  81.             gdi32.TextOutA(dc, x, y, "hello", 5);
  82.             System.Threading.Thread.Sleep(5);
  83.         }
  84.         user32.ReleaseDC(IntPtr.Zero, dc);
  85.     }
  86. }

猜你喜欢

转载自blog.csdn.net/KAMILLE/article/details/2881956