1、第 2 部分 实战练习(自己做的)2.1 c#调用 matlab 函数matlab 版本 2009b,c# 版本 vs2008.2.1.1 matlab 函数编译成 dll 文件(1)首先编写一个函数的 m 文件,如 MatrixOpera 表示两个矩阵相加和相减。%-function addRlt,minusRlt=MatrixOpera(a,b)% 矩阵相加 ,相减m1,n1=size(a);m2,n2=size(b);if m1=m2 | n1=n2display(矩阵大小不相同 )error(参数错误);endaddRlt=a+b;minusRlt=a-b;end%-两个输入参数,两个
2、输出参数,并且都是矩阵形式(2)在 matlab 命令窗口输入 deploytool,弹出如下窗口或者点击 matlab 的主菜单 desktopdeploy tool 获得如下面图所示的窗口,然后在 file newdeployment project 中点击。获得上图窗口,修改工程名称和文件后缀名(必须是,.Net Assembly 格式)修改(3)新建了一个叫 matPrj 的工程(它相当于 c#中的命名空间 namespace) ;然后给它增加 class 或类(它就是 c#中的类) ,点add class比如 myMathClass;之后再给它添加方法(它就是函数了) ,点add f
3、iles,如下图所示。本实例中给它添加了 MatrixOpera 等函数。(4)完了之后就可以编译了。编译出来后需要一两分钟的时间。(5)找到该工程存放的文件夹,从里面拷出 matPrj.dll 文件。同时还要从G:Program FilesMATLABR2009btoolboxdotnetbuilderbinwin32v2.0 拷贝出MWArray.dll 和 ManagedCPPAPI.netmodule。第二个文件必须要哦,否则可能会出错。class方法编译2.1.2 c#添加 matlab 的 dll 引用(1)打开 vs2008,新建一个窗体应用程序。(2)将刚才拷贝到的那 3 个文
4、件一起放在 vs 工程( CallMatlabDllApp)的 debug 文件夹下面。然后右键下图中的引用,选择添加引用,弹出一个窗口,选择其中的浏览页面,分别添加 matPrj.dll 文件和 MWArray.dll 文件。右键,点添加引用已经添加了的引用(3)最后在前面,代码的前面添加下面的命名空间即可。using MathWorks.MATLAB.NET.Arrays;/在MWArray.dll,最常用的using MathWorks.MATLAB.NET.Utility;/ 在MWArray.dll,最常用的using matPrj;/这个就是我们自己定义的,里面有matlab函数如
5、果 matlab 函数复杂,还需要用到其他的空间,则视情况而定,自己凭经验添加。至此,已经可以利用 c#调用我们用 matlab 编写的函数了。2.1.3 函数调用函数调用前必须注意:(1)将 c#的参数输入到 matlab 函数时,要将参数转化为 matlab 的参数形式,通常是 MWArray 类型。(2)matlab 返回的参数,也要转化为 c#用的类型,比如数组或者数值类型。下面是关于(1)和(2)的介绍,从别人那拷过来的,具体可参考http:/ MWArray 数组中的成员直接将数据类型赋值给已经初始化的 MWNumericArray 变量。直接将字符串类赋值给已经初始化的 MWCh
6、arArray 变量。如果是数组类型:直接赋值给 MWNumericArray 变量;赋值给 MWArray 变量,则在前面加上类型转换如:(MWNumericArray)进行强制转换。总之,MWArray 是总类型,其它的以 MW 开头,以 Array 结尾的变量类型都可以直接对它进行赋值或取值。M 类型到 C+/C#数据类型MWArrayM 类型,它是 M 文件的编译后内部的标准类型,一切 C+/C#类型都要最终转换成此类型,方可作为参数调用 M 语言函数。MWCharArrayM 的字符串类型,使用它可以将 M 中的字符类型转换成 C+/C#的字符串类型。MWNumericArray已经
7、添加了的引用MWNumericArray 是 MWArray 与 C#等语言的转换中间类型。常用的转换函数: public Array ToArray(MWArrayComponent component);将 M 类型转换成 C#的 Array 类型,然后可以直接转换成其它类型的数组。 public byte ToScalarByte();将 M 类型转换成 C#的字节类型; public double ToScalarDouble();将 M 类型转换成 C#的双精度类型;double temp = (MWNumericArray)(mwArgout0).ToScalarDouble();
8、 public float ToScalarFloat();将 M 类型转换成 C#的单精度类型; public int ToScalarInteger();将 M 类型转换成 C#的整型类型; public long ToScalarLong();将 M 类型转换成 C#的长整 C/C+/C#数据型类型; public short ToScalarShort();将 M 类型转换成 C#的短整型类型; public override string ToString();将 M 类型转换成 C#的字符串类型; string arror = mwArgout2.ToString(); publi
9、c Array ToVector(MWArrayComponent component);将 M 类型转换成 C#的 Array 类型,然后可以直接转换成其它类型的数组。下面使用调试过的代码示例表述两个函数的区别:double, Temp1 = new double1,3; Temp1= (double,)(MWNumericArray)mwArgout1).ToArray(MWArrayComponent.Real);double s1 = new double2; s1 = (double)(MWNumericArray)mwArgout1).ToVector(MWArrayCompone
10、nt.Real);(3)必须注意到多参数输入和多参数返回的问题。刚开始碰到这个这个问题比较头疼,后来经过不懈的努力,终于从网上找到答案。声明这部分是我参考别人的想法自己写的额,网上百度知道也有我(lwq123_321 )回答的。/输入这里想传入的 2 个输入参数,为了支持矩阵好通用,所以得弄成 Arraydouble a = 1, 2, 3, 4, 5, 6 ;/输入参数 1double b = 2, 4, 6, 8, 10, 12 ;/输入参数 2double, c = new double3, 2;/输出参数 1double, d = new double3, 2;/输出参数 2/这些参数
11、都是矩阵MWNumericArray ma = new MWNumericArray(3, 2, a);/转换成matlab 需求的格式MWNumericArray mb = new MWNumericArray(3, 2, b);/输出参数是一个 MWArray 数组MWArray agrsOut = new MWArray2;/两个输出参数,一定要写数量/输出几个输出参数可以是不同类型的,比如第一个元素是矩阵,第二个是数值/同理,输入参数也是一个 MWArray 数组MWArray agrsIn = new MWArray ma,mb;/调用函数,输出参数需要加 ref 关键字myFun.
12、MatrixOpera(2, ref agrsOut, agrsIn);/2 表示输入参数的个数,输出结构都在 argsOut 中,类似于 c 的指针参数输入/转换得到实际的输出参数MWNumericArray x1 = agrsOut0 as MWNumericArray;MWNumericArray x2 = agrsOut1 as MWNumericArray;c = (double,)x1.ToArray();d = (double,)x2.ToArray();/一定要注意最后 c 和 d 的转化,不同类型的转换差异很大厄/ToArray()对应 n*m 的数组/ToScalarDou
13、ble()对应单个数值/ToVetor()对应 1 维数组到此,已经实现了 c#调用 matlab 函数的整个过程。第 1 部分 他山之石可以攻玉(别人的经验收集)1.1 matlab 与 c#接口的实现http:/ matlab 与 c#之间一些数据类型的转换的方法,我也曾经写过。总结一下,最主要的是要完成下面几个步骤:1、同时安装.netframwork 与 MCR(matlab compile runtime) 。这个在装完 与 matlab 以后,前面 2 个组件也就安装好了。2、利用 matlab 自带的.nettool 工具将.m 文件转换成 .net 组件-.dll 文件为接口,
14、它实际上不含任何实现,都是调用另一个.ctf 文件来完成具体的功能。3、在 c#中,必须引入 mwarray.dll 才能拥有在.net 中进行矩阵运算所需要的一切。虽然 matlab help 中只是说推荐,但一般的应用中,只是进行一部分函数的调用,而不是去取得整个运行结果。这个.dll 是必须引入的。有时mclmcrrt74.dll 这个文件也需要引入。根据具体的要求,需要引入的文件也有所差别。4、生成一个实例,并对.net 组件所输出的结果进行数据类型的转换,以符合.net 编程环境中对数据类型的要求,这个在以前我已经讲过,这里就不再多说了。关键是掌握如何把一个矩阵(在 matlab 中
15、,一个 m*n 的矩阵对应.net 中的一个 1*(m*n)的数组)转换成数据类型一致的数组。目前所有的 matlab 数据类型(无论什么类型,都可以把它看成一个矩阵,这样就可以利用数组的思想来思考)都可以进行转化,具体的可能需要经过实验才能符合各自的要求。虽然 matab 对.net 的支持不如它对 c+支持的功能强大,但也已经满足了我们实际应用的需求。如果我们可以把大部分的运算都放在 matlab 里面完成,数据转换的数量又少,那么整个系统的运行速度与效率还是挺高的。1.2 关于 matlab 与 c#混合编程产生的移植问题http:/ 与 c#混合编程的程序,如果要运行于客户的机子,必须
16、在客户端的机子上设置好系统变量,同时需要安装.netframwork 与 MCR。.netframwork 大家都很熟悉了,任何一个.net 设计出来的程序,都不能脱离.netframwork 而独立运行,正如用 vc+设计的程序离不开 MFC 一样。这个是必须安装的。独立的.netframwork 组件包可以直接去微软的网站上去找。MCR 是由 matlab 提供的,它和.netframwork 的性质相同,任何一个运行matlab 的电脑上,都必须安装该组件。该组件在 matlab2006a 版本中已经分离开而成为一个独立的可运行的.exe 文件。它一般是放在 /MATLAB/R2006a
17、/toolbox/compiler/deploy/win32 文件夹中,名为 MCRInstaller.exe。该组件其实是将 /MATLAB/R2006a/bin/win32 文件夹下的大部分( 注意不是全部).dll 文件打包而已。这也是为什么有些程序在安装了MCR 的机子上仍然不能运行的原因,不过对绝大多数的程序来说,一个 MCR就足够了。比较保险的办法是,自行将/MATLAB/R2006a/bin/win32 下的所有文件打包成一个安装文件,安装完后设置好系统变量(也就是在 class 变量下添加上面文件的路径) 。为了让用户安装程序时不需要太多的操作,我们可以把上面 2 个组件和应用
18、程序一起打包,然后写个脚本检测客户端的机子是否已经安装了上面的 2 个组件,如果没有,则提示用户安装。检测脚本的写法很多地方都可以找到。这里就不多介绍了。1.3 使用转换心得1.3.1 使用把 matlab 的 dll 放到 bin 或者应用程序目录里,添加项目引用. 然后参考该类库的文档,在类里引用 matlab 的命名空间装 matlab ,添加引用VB。NetMatlab = CreateObject(“matlab.application“) MatLab.MinimizeCommandWindow() strMatLab = “t=2:0.2:4*pi;y=sin(t);plot(t
19、,y)“ /这只不过是一个例子,求特征值的 string 要自己查 MatLab.Execute(strMatLab) http:/ 矩阵转换示例用于将 matlab 的返回值矩阵传递到 C#规范的矩阵中MWArray ResOut = null; /用于值输出的 matlab 矩阵ResOut=GTN.GetMatchNo(1,MainAdd, ModelAdd, FName.GTM(), Vaval);MWNumericArray temp = (MWNumericArray)ResOut0; /矩阵转换Array netInterfaceMatrix = temp.ToArray(MWA
20、rrayComponent.Real); /c#规范的矩阵double, location = (double,)netInterfaceMatrix; /变态的强制类型转换http:/ . 8A659077!1836.entry1.3.3 心得等最近在搞 matlab 与 c#混合编程,发现了一些问题,说出来大家讨论一下:(1) matlab 中的乘幂运算是非常好用的,但变成 com 组件后被 C#调用起来真是问题多多,我现在束手无策。c#不支持 sqrt 的写法,连 后面是小数都会抛出异常,真是让人郁闷。(2)matlab 中的画图功能在 c#能得到很好的应用。(3)做成的 com 组件不
21、论是在 matlab 中生成还是在 c#中的初始化都比较耗时间。所以建议大家在这两者混合编程时,尽量考虑清楚那部分功能在那个程序中实现,而不是一股脑的将计算功能交给 matlab,将 GUI 功能交给 c#,这样不仅使程序非常臃肿,而且耗时耗力,出力不讨好。-我实在不甘心自己写的一堆 matlab 程序就这样白白泡汤了,自己又重新想了一下,经过测试我的想法是可行的。1 matlab 中的乘幂运算在 c#中的解决方法:(1)乘幂计算的原始 matlab 函数是 power(x,y) ,在 c#中的函数是 Math.Pow(x,y) ,所以可以将 matlab 中的乘幂运算 (是指幂不是整数时)统统写成 power(x,y)形式。缺点:程序写起来和 c#一样很麻烦,而且 matlab7.4a 也没有向 c#中的函数提示功能,郁闷 ing(2)若 matlab 程序中改动太多且不好改时,可以将乘幂运算交给c#。2 matlab 传参数给 c#时,若是复数是一定要注意用 MWComplex class,否则返回的参数是 null,传过来的参数根本没法用