还是那个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泛型不定类型参数不定参数数量
现在有一个问题,用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泛型不定类型参数不定参数数量
给个例子仅供参考,不知有木有用
没用别喷http://bbs.csdn.net/topics/390381634
//根据模板中的特殊标签自动替换
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)等