C#加载C、C++动态库的方法
来源:互联网 发布:打印机扫描软件通用 编辑:程序博客网 时间:2024/06/16 09:24
1、针对托管动态库的调用
本文章中的外部调用函数声明如下:
public delegate int PutValue(string name, string value);
Assembly ass = Assembly.LoadFile(filePath);//这里是动态库的路径。Type tWorker = ass.GetType(dllType);//dllType是你所需要调用的动态库文件的命名空间+类名(NameSpace.Class)object worker = Activator.CreateInstance(tWorker);//创建对象MethodInfo method = tWorker.GetMethod(PutValue);//需要执行的函数//执行函数,后一个参数即为执行函数需要的参数,若无则为nullmethod.Invoke(tworker, new object[] { "transType", transType });tWorker.InvokeMember("PutValue", BindingFlags.InvokeMethod, null, worker, new object[] { "transType", transType }); //使用这句可以替换上面两句
2、针对非托管动态库的调用
2.1 静态调用
[DllImport(@"XXX.dll", EntryPoint = "PutValue", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]public static extern int PutValue(string name, string value);PutValue("transType", transType);
2.2 动态调用
public class DllInvoke{ public DllInvoke() { } public DllInvoke(string lpFileName) { LoadDll(lpFileName); } // 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递 public enum ModePass { ByValue = 0x0001, ByRef = 0x0002 } [DllImport("Kernel32.dll")] private static extern IntPtr LoadLibrary(string lpFileName); [DllImport("Kernel32.dll")] private static extern IntPtr GetProcAddress(IntPtr hModule, string lpFunName); [DllImport("kernel32.dll")] public static extern bool FreeLibrary(IntPtr hModule); // Loadlibrary 返回的函数库模块的句柄 private IntPtr m_hModule = IntPtr.Zero; // 装载 Dll public void LoadDll(string lpFileName) { m_hModule = LoadLibrary(lpFileName); if (m_hModule == IntPtr.Zero) { throw (new Exception("没有找到:" + lpFileName + ".")); } } // 获得函数指针 private IntPtr LoadFun(string lpFunName) { IntPtr hFuncProc; // 若函数库模块的句柄为空,则抛出异常 if (m_hModule == IntPtr.Zero) { throw (new Exception("函数库模块的句柄为空,请确保已进行 LoadDll 操作!")); } // 取得函数指针 hFuncProc = GetProcAddress(m_hModule, lpFunName); // 若函数指针为空,则抛出异常 if (hFuncProc == IntPtr.Zero) { throw (new Exception("没有找到:" + lpFunName + " 这个函数的入口点.")); } return hFuncProc; } // 卸载 Dll public void UnLoadDll() { if (m_hModule != IntPtr.Zero) { FreeLibrary(m_hModule); m_hModule = IntPtr.Zero; } } // 方法一:使用C#提供的函数进行调用 public object Invoke(string funcName, object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return) { IntPtr hFuncProc = IntPtr.Zero; // 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 if (m_hModule == IntPtr.Zero) { throw (new Exception("函数库模块的句柄为空,请确保已进行 LoadDll 操作!")); } if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length) { throw (new Exception("参数个数及其传递方式的个数不匹配.")); } hFuncProc = LoadFun(funcName); // 下面是创建 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(); for (int i = 0; i < ObjArray_Parameter.Length; i++) { // 用循环将参数依次压入堆栈 switch (ModePassArray_Parameter[i]) { case ModePass.ByValue: IL.Emit(OpCodes.Ldarg, i); break; case ModePass.ByRef: IL.Emit(OpCodes.Ldarga, i); break; default: throw (new Exception("第 " + (i + 1).ToString() + " 个参数没有给定正确的传递方式.")); } } // 判断处理器类型 if (IntPtr.Size == 4) { IL.Emit(OpCodes.Ldc_I4, hFuncProc.ToInt32()); } else if (IntPtr.Size == 8) { IL.Emit(OpCodes.Ldc_I8, hFuncProc.ToInt64()); } else { throw new PlatformNotSupportedException(); } IL.EmitCalli(OpCodes.Calli, CallingConvention.Cdecl, Type_Return, TypeArray_ParameterType); IL.Emit(OpCodes.Ret); // 返回值 MyModuleBuilder.CreateGlobalFunctions(); // 取得方法信息 MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun"); return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值 } // 方法二:使用windows提供的API进行调用 public Delegate Invoke(string lpFunName, Type type) { IntPtr hFunProc = LoadFun(lpFunName); return (Delegate)Marshal.GetDelegateForFunctionPointer(hFunProc, type); } ~DllInvoke() { UnLoadDll(); }}使用方法如下:
public class UnmanagedDynamicLoad{ private static DllInvoke dynamicDll; // 动态加载DLL使用方法一:windows api 加载,简单,建议使用此方法 public delegate int MyPutValue(string name, string value); static MyPutValue PutValue; public static void ReLoadDll(string strDllPath) { if (dynamicDll != null) { dynamicDll.UnLoadDll(); } dynamicDll = new DllInvoke(strDllPath); PutValue = (MyPutValue)dynamicDll.Invoke("PutValue", typeof(MyPutValue)); } // 动态加载DLL使用方法二:C#提供的接口加载 /* private static void PutValue(string name, string value) { object[] Parameters = new object[] { name, value }; Type[] ParameterTypes = new Type[] { typeof(string), typeof(string) }; DllInvoke.ModePass[] themode = new DllInvoke.ModePass[] { DllInvoke.ModePass.ByValue, DllInvoke.ModePass.ByValue }; dynamicDll.Invoke("PutValue", Parameters, ParameterTypes, themode, typeof(int)); } */ //进行调用 public static void doPay(string transType) { try { PutValue("transType", transType); } catch (Exception ex) { throw (new Exception(transType + "支付操作异常:" + ex.ToString())); } dynamicDll.UnLoadDll(); }}
0 0
- C#加载C、C++动态库的方法
- C#动态调用c++DLL的方法
- C#动态调用c++DLL的方法
- C# api 动态加载C++的DLL函数方法
- C 中调用 PostgreSQL 内置动态加载函数的方法
- C++builder(Xe5)下加载VC动态库的两种方法
- 动态加载动态库(C#)反射
- 在C#中调用C语言标准动态库方法
- C语言动态链接库DLL的加载
- Dex动态加载的C语言部分
- Dex动态加载的C语言部分
- Dex动态加载的C语言部分
- C#利用反射动态加载DLL(C#)并调用其中的接口
- 【C#】C#对象的方法
- 【C#】C#的扩展方法
- Linux C动态加载SO库文件
- PHP5加载|安装外部C动态库
- C#调C的动态库遇到的问题
- PL/SQL8 连接远程Oracle服务器
- 设计模式——原型模式
- JAVA API 实例
- iOS设计模式(十) 享元模式
- hdu 4300 Clairewd’s message
- C#加载C、C++动态库的方法
- Git代码行统计命令集
- unorder_map和map的区别。
- vim插件phpcheck安装与使用 -- 高效的检查php语法错误
- 【例题】【线段数】lazy_
- Android图片选择器
- R函数对比
- 廖雪峰python学习笔记6:条件判断、循环
- 自定义View---widthMeasureSpec和heightMeasureSpec是从哪来?