生成dll文件:MyDll.dll
在C#中调用dll文件一般需要声明:
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MyFun( int a, int b);
这样想动态来加载dll没办法操作。
后来在网上查了下,有两种方式能够动态的加载dll,不用声明:
先准备好DllInvoke类
public class DllInvoke { #region Win API [DllImport("kernel32.dll")] private extern static IntPtr LoadLibrary(string path); [DllImport("kernel32.dll")] private extern static IntPtr GetProcAddress(IntPtr lib, string funcName); [DllImport("kernel32.dll")] private extern static bool FreeLibrary(IntPtr lib); #endregion private IntPtr hLib; public DllInvoke(String DLLPath) { hLib = LoadLibrary(DLLPath); if (hLib == IntPtr.Zero) { throw (new Exception("没有找到:" + DLLPath + "。")); } } ~DllInvoke() { FreeLibrary(hLib); } public IntPtr GetIntPtr(string APIName) { IntPtr api = GetProcAddress(hLib, APIName); if (api == IntPtr.Zero) { throw (new Exception(" 没有找到 :" + APIName + " 这个函数的入口点 ")); } return api; } //将要执行的函数转换为委托 public Delegate GetDelegate(string APIName, Type t) { IntPtr api =GetIntPtr(APIName); return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t); } }
方法一:
delegate int Add(IntPtr[] X, int r, int c); DllInvoke dk = new DllInvoke("MyDll.dll"); Add addFunction = (Add)dk.GetDelegate("MyFun", typeof(Add)); int sum=addFunction(2,3);
方法二:
object[] par = new object[] {2,3 };//输入参数 Type[] parType = par.Select(s=>s.GetType()).ToArray();//输入参数的类型 //Type[] parType =new Type[]{typeof(int),typeof(int)}; Type Type_Return = typeof(int); // 返回类型 AssemblyName assemblyName = new AssemblyName("InvokeName");//名称随便写 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("InvokeModule"); MethodBuilder methodBuilder = moduleBuilder.DefineGlobalMethod("InvokeMethod", MethodAttributes.Public | MethodAttributes.Static, Type_Return, parType); ILGenerator IL = methodBuilder.GetILGenerator(); for (int i = 0; i < par.Length; i++) {// 依次压入堆栈 IL.Emit(OpCodes.Ldarg, i); //实参传送方式,byValue // IL.Emit(OpCodes.Ldarga, i);//实参传送方式,byRef } //要调用的dll DllInvoke dk = new DllInvoke("MyDll.dll"); //调用的方法 IntPtr farProc = dk.GetIntPtr("MyFun"); 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, parType); IL.Emit(OpCodes.Ret); moduleBuilder.CreateGlobalFunctions(); //方法名和上面的一致 MethodInfo MyMethodInfo = moduleBuilder.GetMethod("InvokeMethod"); object sum = MyMethodInfo.Invoke(null, par);// 调用方法,并返回其值