C#与Matlab的交互

matlab与C#交互方式

  • .NET组件
  1. 说明

利用m文件生成dll再由C#调用。优点是可移植型较好,目标机不需要安装Matlab,只需要安装MCRinstaller.exe及dll的注册,缺点是配置较为复杂,受各种版本的影响。此方法编译时候选择的.NET版本必须与VS中建立的工程的.NET版本一致,并且64位matlab编译的dll文件必须在VS中选择64位编译器.

 

  1. 步骤

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类型的二维数组.

 

  1.  常见问题

如果出现类似于下面的错误

则表示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

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表示执行成功