唉,在做支持向量机分类优化实验的时候,支持向量机的c#代码写的头疼。有些核函数和分类训练函数不会写,搞得头疼。后来听同学介绍说matlab里面有包直接可以用,我又去载了一个R2015a最新的matlab,特么现在又遇到问题。Matlab语法不会啊,咋用??
然后我查了些资料,说vs2008可以和matlab进行混合编程,如果能实现,将会减少很多的工程量。我看了网上的教程,都以vs2008和matlab2010a为例进行的,而这个和最新的matlab2015a还是有很大的区别,最后我打算去重新做一次。
注意: 下面进行实验的版本是 vs2008和MatlabR2015a
只要按照我下面的步骤一步步下去,一定能实现。
一、VS准备阶段
1. 先建一个C# 接口,在C# 里面新建一个类库,为了命名易懂,我们命名为DemoTestInterface :如下图所示:
2. 然后 点击“生成”-》配置管理器。
3. 我的matlab是64位的,所以把平台的配置改为×64.
(从活动解决方案平台那里添加)
4. 然后我们添加MWArry.dll , 右键添加引用, 路径为:..\MATLAB\toolbox\dotnetbuilder\bin\win32\v2.0\
本机的位置是:
(有些vs2008的位置是在,可以直接在.Net 选项卡中找到, MathWorks, .NET MWArray API。 在此选项卡中,按键盘上的“ M”,出现的第一个,就是所要的文件。 VS2010 中目前未能实现通过此方法添加。 也可以与 VS2010 一样,在浏览中添加,我在我的vs里面是没有找到这个东西,,尴尬~~)
添加后的内容为:
然后在添加using 命名空间。并修改类类型为 Interface 和相应的接口名。 并注意接口名与命名空间名不能一样。如下图所示:、
接下来我们拿矩阵乘法的例子进行示范:
添加所需要实现的 Matlab 函数声明,本例中实现的是两个矩阵的乘法,添加声明,其中
MWNumericArray 是 Matlab 与 C#的变量转换中间类,此处,只需要给出主函数的声明,子函数不需要声明。 如下图所示:
然后生成此接口(在bin/x64/debug目录下有
这个dll为接口。),待后面使用。
二、 matlab实现阶段
编写需要实现的主函数,函数名需要与 C#声明的函数名相同。如果需要使用到子函数,一
并编写子函数,此处使用子函数,将矩阵乘以 1。 由于本文只是一个示例,所以具体的变量保护的措施,建议最好在 C#调用 Matlab 之前就做好,结合本例,如两个矩阵不一样大小、等等。 注意主函数中的“ double”,如果希望主 C#调用的结果是 double 型的,此处需要强制转换成 double。
我在这里写了两个函数 MatrixMultiply 和SubFun
然后新建一个 Matlab 工程,直接在 Command Window 中输入 deploytool 创建,如下:
然后选择第三个liabrary compiler
得到下面一个界面:
我们将我们的工程名字命名为MatlabMultiply.prj。如下图所示:
同时很关键的一点: 把类型改成 .NET Assembly ,
然后我们添加功能函数:
然后 把右边的滚动条拉到最下面,我们进行设置。
需要设置两个地方,一个是.Net 设置,另一个是 Type Safe API,在.Net 设置中, Microsoft Framework 默认选择是 default,将此处按照目标环境修改,如 VS2008 就选择 3.5, VS2010 选择 4.0。 这里选择3.5。
在 Type Safe API 设置中,需要将上一步骤生成的接口文件复制到当前 Matlab 函数的文件夹中,并在 Interface assembly 中选中。如下图所示:
然后我们进行打包:
点击“Package”。
等待其完成。。。
这样就表示完成了。我们可以打开生成文件,
生成的文件中一般需要用到的有如下三个文件,
class1DemoTest.dll、 MatlabMultiplyNative.dll和 DemoTestInterface.dll。 特别的是,第二个文件,在 for_resdistribution_files_only 文件夹中,有一个名字类似,但是不带 Native 的文件,此文件不需要。 第三个文件,是此前 C#生成的接口文件。将此三个文件复制到需要调用的工程中,并添加引用。下一节会给出具体调用方法。
三、组合阶段
我们建一个简单的控制台程序。
添加刚才在matlab生成的接口dll文件。即 添加引用。 同时添加 MWArray.DLL接口文件。
然后在代码上端添加四个命名空间
然后以 Matlab 三个文件中的第一个文件 CSIDemoTest.dll 的文件名 CSIDemoTest 为类名,实例化一个类。然后编程:
我们进行调试,,
由此可以观察到,, 已经通过matlab实现矩阵的乘法。
下面的几个点是由大牛那里知道的:
特此说明;。
关于中间类的说明:数据类型到 M 类型:如果 C++/C#数据不是数组,直接将值传递给已经初始化的 MWArray 数组中的成员。 直接将数据类型赋值给已经初始化的 MWNumericArray 变量。 直接将字符串类赋值给已经初始化的 MWCharArray 变量。如果是数组类型,直接赋值给 MWNumericArray 变量;赋值给 MWArray 变量,则在前面加上类型转换如:( MWNumericArray)进行强制转换。 总之, MWArray 是总类型,其它的以MW 开头,以 Array 结尾的变量类型都可以直接对它进行赋值或取值。M
类型到 C++/C#数据类型MWArray M 类型,它是 M 文件的编译后内部的标准类型,一切 C++/C#类型都要最终转换成此类型,方可作为参数调用 M 语言函数。
MWCharArray M 的字符串类型,使用它可以将 M 中的字符类型转换成 C++/C#的字符串类型。MWNumericArray 是 MWArray 与 C#等语言的转换中间类型。常用的转换函数:
1、 public Array ToArray(MWArrayComponent component);
将 M 类型转换成 C#的 Array 类型,然后可以直接转换成其它类型的数组。
2、 public byte ToScalarByte();
将 M 类型转换成 C#的字节类型;
3、 public double ToScalarDouble();
将 M 类型转换成 C#的双精度类型;
double temp = ((MWNumericArray)(mwArgout[0])).ToScalarDouble();
4、 public float ToScalarFloat();
将 M 类型转换成 C#的单精度类型;
5、 public int ToScalarInteger();
将 M 类型转换成 C#的整型类型;
6、 public long ToScalarLong();
将 M 类型转换成 C#的长整 C/C++/C#数据型类型;
7、 public short ToScalarShort();
将 M 类型转换成 C#的短整型类型;
8、 public override string ToString();
将 M 类型转换成 C#的字符串类型;
string arror = mwArgout[2].ToString();
9、 public Array ToVector(MWArrayComponent component);
将 M 类型转换成 C#的 Array 类型,然后可以直接转换成其它类型的数组。
下面使用调试过的代码示例表述 1 和 9 两个函数的区别:
1、 double[,] Temp1 = new double[1,3];
Temp1= (double[,])((MWNumericArray)mwArgout[1]).ToArray(MWArrayComponent.Real);
9、 double[] s1 = new double[2];
s1=(double[])((MWNumericArray)mwArgout[1]).ToVector(MWArrayComponent.Real);
从以上代码可以看出:函数 1 得到了二维数组,而 9 则是得到了一维数组。转换成 C++/C#数据类型后,它们的维数均为从 0 开始。