之前做一个项目,需要动态调用DLL,而且动态调用别人都已经写好了,我只要修改就好了,但是发现DLL只是返回了一个值没有去show出来,我就郁闷掉了,然后各种找怎么获取返回值,其中有一个人的代码是通过非托管函数名转换为对应的委托,
///<summary> ///通过非托管函数名转换为对应的委托, by jingzhongrong ///</summary> ///<param name=”dllModule”>通过LoadLibrary获得的DLL句柄</param> ///<param name=”functionName”>非托管函数名</param> ///<param name=”t”>对应的委托类型</param> ///<returns>委托实例,可强制转换为适当的委托类型</returns> public static Delegate GetFunctionAddress(int dllModule, string functionName, Type t) { int address = GetProcAddress(dllModule, functionName); if (address == 0) return null; else return Marshal.GetDelegateForFunctionPointer(new IntPtr(address), t); }
然后在页面上面去调用方法,在赋值
Add foo = (Add)LoadDLL.GetFunctionAddress(hModule, "Add", typeof(Add)); result = foo(1, 22); Console.Write(result);
但是后来我发现其实我的代码已经返回了,我只要去show出来就好了
后台代码
/// <summary> /// 调用所设定的函数 /// </summary> /// <param name="ObjArray_Parameter"> 实参 </param> /// <param name="TypeArray_ParameterType"> 实参类型 </param> /// <param name="ModePassArray_Parameter"> 实参传送方式 </param> /// <param name="Type_Return"> 返回类型 </param> /// <returns> 返回所调用函数的 object</returns> public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, InitStaticData.ModePass[] ModePassArray_Parameter, Type Type_Return) { // 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 if (hModule == IntPtr.Zero) throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); if (farProc == IntPtr.Zero) throw (new Exception(" 函数指针为空 , 请确保已进行 LoadFun 操作 !")); if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length) throw (new Exception(" 参数个数及其传递方式的个数不匹配 .")); // 下面是创建 MyAssemblyName 对象并设置其 Name 属性 AssemblyName MyAssemblyName = new AssemblyName(); MyAssemblyName.Name = "InvokeFun"; // 生成单模块配件 AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName, AssemblyBuilderAccess.Run); ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll"); // 定义要调用的方法 , 方法名为“ MyFun ”,返回类型是“ Type_Return ”参数类型是“ TypeArray_ParameterType ” MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod("MyFun", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType); // 获取一个 ILGenerator ,用于发送所需的 IL ILGenerator IL = MyMethodBuilder.GetILGenerator(); int i; for (i = 0; i < ObjArray_Parameter.Length; i++) { // 用循环将参数依次压入堆栈 switch (ModePassArray_Parameter[i]) { case InitStaticData.ModePass.ByValue: IL.Emit(OpCodes.Ldarg, i); break; case InitStaticData.ModePass.ByRef: IL.Emit(OpCodes.Ldarga, i); break; default: throw (new Exception(" 第 " + (i + 1).ToString() + " 个参数没有给定正确的传递方式 .")); } } 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, TypeArray_ParameterType); IL.Emit(OpCodes.Ret); // 返回值 MyModuleBuilder.CreateGlobalFunctions(); // 取得方法信息 MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun"); return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值 }
前台:MessageBox.Show(myfun.Invoke(Parameters, ParameterTypes, themode, Type_Return).ToString());
弯弯绕绕绕死我了