C#和MatLab的混合编程,充分利用了winform的直观显示和matlab的强大计算能力。在此以一个小例子的形式给大家讲述一下二者混合编程的实现。
一、软件的配置说明
C#版本:VS2010 matlab版本:matlab2013a
二、把 matlab函数编译成dll文件
2.1首先写一个函数的.m文件(如下函数MatrixOpera实现两个矩阵的相加和相减)
%-------------------------------------------------------- function [addRlt,minusRlt]=MatrixOpera(a,b) % 矩阵相加,相减 [m1,n1]=size(a); [m2,n2]=size(b); if m1~=m2 || n1~=n2 display(‘矩阵大小不相同‘) error(‘参数错误‘); end addRlt=a+b; minusRlt=a-b; end %-----------------------------------------------------------
2.2 创建制作的dll文件的工程
在MatLab的命令窗口中,输入deploytool打开创建dll文件的工程创建窗口,如下图所示
在图中,主要分为三部分,Name:你想要命的工程名,prj是工程的后缀;Location:创建工程的储存位置;Type:针对c#而言,我们需要选择.NET Assembly这一项
点击Ok选项,工程已经创建完毕
2.3 向所建工程中添加对应的元素并编译
上述过程中,新建了一个叫matPrj的工程(它相当于c#中的命名空间namespace);然后给它增加class(它就是c#中的类),点[add class]添加myMathClass;之后再给它添加方法(它就是函数了),点[add files],本实例中选中之前编写的MatrixOpera函数。完了之后就可以编译了,编译需要一两分钟的时间,如下图所示
三、C#中添加matlab的dll引用
3.1打开vs2011,新建一个窗体应用程序
3.2完成dll文件的拷贝
将matlab工程(matPrj)src文件夹下的matPrj.dll和D:\Program Files\MATLAB\R2013a\toolbox\dotnetbuilder\bin\win64\v2.0(前边为matlab的安装路径)文件夹下的MWArray.dll拷贝到VS工程(CallMatlabDllApp)下的\bin\Debug文件夹下
3.3在VS里添加dll文件的引用,然后在代码前引用相应的命名空间
如果matlab函数复杂,还需要用到其他的空间,则视情况而定,自己凭经验添加。
至此,已经可以利用c#调用我们用matlab编写的函数了。
四、在C#中调用matlab提供的函数
matlab中一个m*n的矩阵对应.net中的一个1*(m*n)的数组,因此在C#中调用matlab函数的关键是掌握数据类型一致的一个矩阵与一个数组之间的转换。包括以下两个问题:
a、将C#中的参数输入到matlab函数时,要将参数转化为matlab的参数形式,通常是MWArray类型
b、matlab函数返回的参数,也要转化为C#用的类型,比如数组或者数值类型
在C#中调用本例函数的代码如下:
matPrj.myMathClass test = new matPrj.myMathClass(); //将myMathClass类实例化 double[] a = { 1, 2, 3, 4, 5, 6 };//定义两个输入参的值 double[] b = { 1, 1, 1, 1, 1, 1 };//它们是两个一维数组 double[,] c = new double[3, 2];//定义C#中接收输出参数的类型 double[,] d = new double[3, 2];//是两个二维数组 //把两个输入参数都转换成中间类型,中间类型也是矩阵所以要指明维数 //这里将两个输入参数转换为两个三行两列的矩阵 MWNumericArray matlab_a = new MWNumericArray(3, 2, a); MWNumericArray matlab_b = new MWNumericArray(3, 2, b); //输入参数成功转化为一个MWArray矩阵 MWArray[] agrsIn = new MWArray[] { matlab_a, matlab_b }; //声明输出参数是一个MWArray矩阵两个输出参数,一定要写数量 MWArray[] agrsOut = new MWArray[2]; //调用matlab函数,2表示输入参数的个数,输出参数前需要加 ref 关键字 //此例实现了两个三行两列的矩阵相加减 test.MatrixOpera(2, ref agrsOut, agrsIn); //把两个输出参数转换成中间类型 MWNumericArray net_c = agrsOut[0] as MWNumericArray; MWNumericArray net_d = agrsOut[1] as MWNumericArray; c = (double[,])net_c.ToArray();//输出参数成功转化为二维数组 d = (double[,])net_d.ToArray(); //一定要注意最后c和d的转化,不同类型的转换差异很大厄 //ToArray()对应n*m的数组 //ToVetor()对应1维数组 //ToScalarDouble()对应单个数值 for (int i = 0 ; i <= 2; i++)//输出结果验证 { for (int j = 0; j <= 1; j++) { textBox1.Text += c[i, j].ToString() + " "; textBox2.Text += d[i, j].ToString() + " "; } textBox1.Text += "\r\n";//换行 textBox2.Text += "\r\n"; }
MWNumericArray是MWArray与C#等语言数据转换中间类,实现C#与matlab函数间传递参数的功能
MWArray是总类型,其它的以MW开头,以Array结尾的变量类型都可以直接对它进行赋值或取值,它是.m文件的编译后内部的标准类型,一切C#类型都要最终转换成此类型,方可作为参数调用matlab函数
我在运行上述程序时,第一句将myMathClass类实例化报错
但是单看这语句是没有任何问题的
matPrj.myMathClass test = new matPrj.myMathClass();
查阅了关于错误的信息,但是解决的都基本是换了一个matlab版本才解决的,偶然看见说HRESULT:0x8007000B的错误和编译平台有些关系,就开始着手试试是不是因为我这平台的问题导致的,果然,换了编译的平台就好了。
具体解决:
1:右键项目名称—>属性—>生成
2:目标平台选择x64
再次运行程序,结果如下:
上述结果同下图在matlab中实现效果相同,验证结果的正确性
脱离matlab安装的环境下,如何实现程序的运行自如:
通过com组建的形式进行混合编程,如果机器上没有安装MATLAB,编译生成的软件照样可以使用,但是需要安装MATLAB提供的MATLAB Compiler Runtime(MCR),这个软件在MATLAB的安装目录下:X:\MATLAB\R2013a\toolbox\compiler\deploy\win32\MCRInstaller.exe(X是MATLAB安装的盘符),如果你的电脑上安装了MATLAB,则不需要在重新安装这个软件。另外,不同的MATLAB版本提供的MATLAB Compiler Runtime可能会不同,如果在另一台电脑上自己编写的软件运行有问题,可能是编译器的版本不同引起的
参考资料:http://wenku.baidu.com/link?url=mgBBgQFt89s-7rKrNbJ-630AH0q_2mMMYBbvCWx9IiGkuOQ7qFTkL_pZRhT5FqazmtFoD6UUM6vWLeDrprF2OAGqUcmrHEugVntjWvzCwxy
http://www.cnblogs.com/liuxiaowei0543/p/3682377.html
http://wenku.baidu.com/view/6ad3b62b59eef8c75fbfb3ed.html