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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 360云盘的东西删不了怎么办 手机邮箱打开的文件疑似病毒怎么办 电脑qq发送的文件失效了怎么办 小米4c温控文件打开是乱码怎么办 超星尔雅用学号登录密码忘了怎么办 全脸做激光去黄褐斑后脸发红怎么办 上传到微云中的视频下载不了怎么办 微云保存的小电影下载不了怎么办 苹果手机下载有云朵下载不了怎么办 手机下载登录忘了密码了怎么办 软软件被手机加密忘了密码怎么办 苹果手机想下载东西忘了密码怎么办 已经不念书几年了突然想上学怎么办 江湖风云录把王老爷子杀了怎么办 练扫踢胫骨旁边的肌肉受伤了怎么办 四个月宝宝没抱住摔了头部怎么办 老公老是跟年轻的小姑娘聊天怎么办 老婆出轨老公想离婚又舍不得怎么办 孕妇打完无痛分娩针就想睡觉怎么办 熟食店开空调菜品吹的很干怎么办 不锈钢锅在液化气烧了发黄怎么办 在小镇门面卤菜店不好卖怎么办? 被辣椒辣到嘴唇了该怎么办 沁园净水机不制水指示灯不亮怎么办 太辣了辣得胃疼怎么办 出现连接问题或mmi码无效怎么办 存折丢了怎么办卡号也不记得了 车内皮子被烂苹果腐蚀有印怎么办 锅被腐蚀后变黑色应该怎么办 后厨炉灶里的炉芯进水了怎么办 小儿九个月老是流黄鼻子该怎么办 肉炖的老了不烂怎么办 吃了凉东西现在一直打嗝应该怎么办 喝了很多水还是觉得口渴怎么办 刚买的猪肝没洗直接炒了怎么办 四个多月的宝宝吃了脏东西怎么办 狗吃了脏东西拉稀呕吐怎么办 五个月宝宝怕吃药导致奶不喝怎么办 蒸锅锅盖吸住了怎么办锅比锅盖要大 豇豆没熟孕妇吃了中毒怎么办 孩子积食拉不出粑粑憋的直哭怎么办