利用m文件生成dll再由C#调用。优点是可移植型较好,目标机不需要安装Matlab,只需要安装MCRinstaller.exe及dll的注册,缺点是配置较为复杂,受各种版本的影响。此方法编译时候选择的.NET版本必须与VS中建立的工程的.NET版本一致,并且64位matlab编译的dll文件必须在VS中选择64位编译器.
File->New->Deployment Project Type一定要选择.Net Assembly
新建一个工程名为robotSimulation
选择对应.Net版本,并添加m文件
将类名改为CalculateTheta,编译
拷贝distrib目录下生成的类库文件,
在C#中引用上面的robotSimulation.dll文件。找到matlab安装目录下的MWArray.dll文件
在C#项目中引用上面的dll文件,并在代码中使用如下名字空间:
using MathWorks.MATLAB.NET.Arrays;
using MathWorks.MATLAB.NET.Utility;
using robotSimulation;
在程序中可以直接新建CalculateTheta类型的对象,并调用CalculateThetaByCoordinate及CalculateThetaByCoordinate_Palm方法,如下:
CalculateTheta ct = new CalculateTheta();
MWArray array=ct.CalculateThetaByCoordinate_Palm(33.26, 1.52, 105.49, 20.871, 50.059, 44.621, 25.014, 20, -30,0);
MWNumericArray result = (MWNumericArray)array;
double[,] csArray = (double[,])result.ToArray(MWArrayComponent.Real);
matlab中CalculateThetaByCoordinate_Palm定义如下,
返回结果为4个浮点数,因此可以使用MWNumericArray类转化,并最终转化成double类型的二维数组.
如果出现类似于下面的错误
则表示matlab的版本与VS选择的编译器不一致,比如matlab为64位,而选择的编译器为x86或者Any CPU,这时只需要将编译器选择X64即可
关于传输参数问题
- MWNumericArray是MWArray和c#中数据的中间类,怎么用?怎样在C#与matlab间传递参数?
a.double型、int型等数值类型的变量传递
MWNumericArray i = null, result = mydouble;
i=4;
myClass myclass = new myClass(); //实例化
result = (MWNumericArray)myclass.myfunc(i);
b.字符串(需要用到MWCharArray和MWArray转换)
MWCharArray FileName = myString;
MWNumericArray sensitivity;
sensitivity = (MWNumericArray)myClass.myAlgorithm((MWArray)FileName);
c.多个输出参数组成的数组
MWNumericArray out_Arr = (MWNumericArray)out_Args[1]; //取出第一个参数返回的数组(matlab返回的数组下界是从1开始的)
取出数组中的一个元素值
mydouble=out_Arr[i].ToScalarDouble();
如上面例子ToScalarDouble一类的toXXXX等方法还有许多,慢慢发掘吧。
d.result.toArray可以把matlab返回的矩阵变成C#的n x m数组,eg:
double[,] csArray= (double[,])result.ToArray(MWArrayComponent.Real);
e.将数组传入Matlab(和传递单个数值的方法一样) //4月26日添加
double[,] dbx = new double[2, 2] { { 1, 2 }, { 3, 4 } };
MWNumericArray x=dbx;
myclass.picture(x);
其中picture是一个自己写的m函数,内容是plot(x),用于验证传入的矩阵的结果。
添加MWArray.dll的引用,并添加COM组件Matlab Application Type Library,如下图:
在程序中使用名字空间
using MLApp;
matlab = new MLAppClass();//新建一个对象
matlab.Visible = 0;//打开时候窗口不可见
matlab.Execute(@"cd 'D:\Program Files\MATLAB\R2010b\bin\myWorkSpace\'");//执行命令
string cmd ="[result]=CalculateThetaByCoordinate_Palm(30)");//计算结果中result = 20 12 22 50
matlab.Execute (cmd);//该函数返回一个字符串,在本次执行中返回ans = 20 12 22 50
double[,] values = (double[,])matlab.GetVariable("result","base");//获取matlab函数CalculateThetaByCoordinate_Palm执行结果,返回结果为二维数组
matlab.Quit();//退出
libeng.dll文件位于安装目录的R2010b\bin\win64\目录下,拷贝到工程的可执行文件目录下,或者拷贝到操作系统的System32(64位操作系统对应sysWow64)。该dll文件为非托管文件,不可直接引用,而必须使用DllImport类引用。(DllImport位于名字空间System.Runtime.InteropServices下)
[DllImport("libeng.dll")]
static extern IntPtr engOpen(string startcmd);
[DllImport("libeng.dll")]
static extern int engPutVariable(IntPtr ep, string var_name, IntPtr ap);
[DllImport("libeng.dll")]
static extern int engEvalString(IntPtr ep, string str);
[DllImport("libeng.dll")]
static extern IntPtr engGetVariable(IntPtr ep, string name);
[DllImport("libeng.dll")]
static extern int engClose(IntPtr ep);//0 表示关闭成功,返回 1 表示发生错误
public IntPtr engine = IntPtr.Zero;
//打开matab引擎
engine = engOpen(null);
if (engine != IntPtr.Zero)
{
//打开成功
}
engClose(engine);//关闭matlab引擎,返回0表示成功
engEvalString(engine, command)//执行命令command,返回0表示执行成功