还是那个C# winform调用非托管dll(纯C或者C++编写)的老问题,经过论坛大神们的指点,我已经摸索出了完全动态加载使用\卸载dll的方法。
现在有一个问题,用C#做出来的程序需要加载各种非托管dll,这些dll中的导出函数的参数类型和数量不确定。C#中要使用非托管dll中的导出函数就得声明一个和导出函数型式一样的委托(型式一样指的是返回类型和参数类型、数量一样,名字一不一样无所谓)
比如有个dll的导出函数是这样的extern "C" _declspec(dllexport) double Frequency(int n,unsigned char* epsilon);
我要在C#中使用这个函数就得声明一个委托:[UnmanagedFunctionPointer(CallingConvention.Cdecl)]delegate double RunTest_func_01(int n,byte[] epsilon);(方括号里的修饰符意义是允许非托管dll修改C#传递过去的数据)
然后加载dll,然后这样使用那个函数PvalueResult = launchdll(func_01_n, TestSourceEpsilon);(PvalueResult是double类型变量,func_01_n是int类型变量,TestSourceEpsilon是初始化好有内容的byte数组名字)现在就存在一个问题:如果想要使用不同的dll就得知道dll中导出函数的具体形式,但这程序最好能实现随时加载未知的dll,通过用户给的XML配置文件得到其参数的数量和类型,这就需要在声明函数委托时使用一个可以使用可变参数类型、数量的方法(最好返回类型也可变),我查了查google发现.net中的泛型好像可以实现这种功能,但是讲的都很含糊,有木有大神能根据上面指点一下具体的使用方法。
PS.如果真能实现,我会总结出一份完整的C#动态使用非托管dll运行未知导出函数的文档放在博客中造福大家,毕竟现实项目中C#和C、C++联合编程的情况很常见,而大部分人都不怎么会用非托管dll非托管dll泛型不定类型参数不定参数数量

解决方案 »

  1.   

    PS.那个运行函数中的launchdll是我自己封装的动态加载dll类中的一个变量,和函数声明无关
      

  2.   

    不懂
    给个例子仅供参考,不知有木有用
    没用别喷http://bbs.csdn.net/topics/390381634
      

  3.   


    //根据模板中的特殊标签自动替换
            public string GetHtmlByMoban(string url)
            {
                //这是一个读取模板内容的方法,可替换为自己需要的
                string str = CreatHtmlBLL.ReadHtmlMod("~/HtmlMode/" + url + ".html");
                string pattern = @"{#(\w+)\((?:(.+?))\)";//拆分成方法名GetNewsByArticle和参数9,10,语文,参数可含中文
                Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
                MatchCollection mc = reg.Matches(str);
                foreach (Match m in mc)
                {
                    string FuncName = m.Groups[1].Value;
                    string Para = m.Groups[2].Value;
                    string Datastr = string.Empty;
                    try
                    {
                        Datastr = ExecuteDLL("BLL", "CreateIndex", FuncName, Para);
                    }
                    catch (Exception e) { Datastr = "标签" + FuncName + "替换时出现问题,异常信息:" + e.Message; }
                    str = str.Replace("{#" + FuncName + "(" + Para + ")}", Datastr);
                }
                return str;
            }
    public string ExecuteDLL(string path, string className, string MethodName, string pstr)
            {
                //先从程序集中查找所需要的类并使用系统激活器创建实例
                object instance = Assembly.Load(path).CreateInstance(path + "." + className);
                Type type = instance.GetType();
                object[] parameters = null;
                if (pstr != "")
                {
                    string[] pa = pstr.Split(',');
                    parameters = new object[pa.Length];
                    for (int i = 0; i < pa.Length; i++)
                    {
                        if (StrChangeBLL.IsInt(pa[i]))
                            parameters[i] = int.Parse(pa[i]);
                        else
                            parameters[i] = pa[i];
                    }
                }
                //查找指定的方法,然后返回结果
                MethodInfo methodinfo = type.GetMethod(MethodName);
                return methodinfo.Invoke(instance, parameters).ToString();
            }需要引用 using System.Reflection;
    调用方法:string Datastr = ExecuteDLL("BLL", "CreateIndex", "GetPicTitle", Para);
    此方法表示调用BLL命名空间中CreateIndex类的GetAllPic方法,后台Para是此方法的所有参数上例是一个从html模板里自动替换标签为所需内容的方法
    比如模板中有{#GetPicTitle(3,4,1,12,52)},{#GetAll(10,2,1)}等标签,方法名和参数个数全是未知
    使用ExecuteDLL方法可分别调用BLL.CreateIndex.GetPicTitle(3,4,1,12,52)和BLL.CreateIndex.GetAll(10,2,1)等
      

  4.   

    昨天把object装箱和泛型都试了一遍,结果发现,用C语言和C++写的非托管dll内的导出函数根本不支持.net的这些高端面向对象特性,只能老老实实的按照导出函数的形式来声明委托函数