Author: binzhouweichao@163.com
Copyright 2013, binzhouweichao@SDU, All Rights Reserved.
Date: 2013-11-07
C#与Matlab混合编程基础过程。
参考:
http://blog.csdn.net/zilin82/article/details/5466087
http://blog.sina.com.cn/s/blog_4b94ff130100d4uf.html
系统平台:
Windows 7 Ultimate x64
软件版本:
C#:Visual Studio 2010
Matlab:MATLAB R2011b x64(或更高版本,安装版和绿色免安装版均可,需要激活Compiler组件的License)
注:
虽然
a. VS2010不区分32位和64位系统,只区分二者的编译器;
但是
b. Matlab区分32位和64位系统;
所以
64位系统平台下只能编译64位的matlab接口,在vs2010中引用时,vs必须配置成64位平台编译。具体配置过程下面会有介绍。
32位系统无须配置vs的编译器。
1. 设置Matlab对外接口
打开Matlab,在默认的当前文件夹(Current Folder)下即可,一般为安装目录的bin目录,2013b可能是我的文档下的MATLAB目录。
新建M文件,实现两个向量(或数字)的相加,命名为sumab,位置放在默认当前文件夹下即可:
function [tsum] = sumab(a, b)
tsum = sum([a, b]);
end
首先,配置选择C#的混合编译器VS2010,在Matlab的命令窗口(Command Window)中,键入:
mbuild -setup
会弹出:
Would you like mbuild to locate installed compilers [y]/n?
在弹出的选择项中,使用默认的[y](直接回车就是选择默认值),让Matlab自动搜索可用的编译器。
如果只安装了vs2010,会弹出可选编译器为:
Select a compiler:
[1] Microsoft Visual C++ 2010 in C:\Program Files (x86)\Microsoft Visual Studio 10.0
[0] None
Compiler:
填写1,回车:
Please verify your choices:
Compiler: Microsoft Visual C++ 2010
Location: C:\Program Files (x86)\Microsoft Visual Studio 10.0
Are these correct [y]/n?
确认,直接回车即可。
****************************************************************************
Warning: Applications/components generated using Microsoft Visual C++
2010 require that the Microsoft Visual Studio 2010 run-time
libraries be available on the computer used for deployment.
To redistribute your applications/components, be sure that the
deployment machine has these run-time libraries.
****************************************************************************
Trying to update options file: C:\Users\xxx\AppData\Roaming\MathWorks\MATLAB\R2011b\compopts.bat
From template: D:\MATLAB\R2011B~1\bin\win64\mbuildopts\msvc100compp.bat
Done . . .
其次,使用部署工具,建立.Net接口工程,在Command Window中,键入:
deploytool
在弹出的部署工程对话框中,将工程名命名为sumab,Location默认,Type类型选择.NET Assembly:
点击上图所示的窗体的最大化按钮,使得新添加的窗体最大化:
要想还原,点击上图所示的按钮即可。
给新建的.NET工程添加新类,点击Build选项卡下的Add Class,添加一个新类,命名为Sumab,再点击新类下面的Add files,选择前面建立的sumab.m函数文件:
然后点击上图所示的编译按钮,编译此工程。大约1分钟左右。
编译完成后,点击Close关闭即可。
注:若出现mcc failed错误,或者cannot find ‘Compiler’,说明MATLAB Compiler工具的License未激活,解决方法是重新激活Matlab,或者重新安装已经激活Compiler工具的Matlab版本。
上述工程生成的接口dll文件位于工程所在目录(本例中为Matlab的默认current folder,即D:\MATLAB\R2011b_x64\bin)下的同名的子目录中。
里面有两个子目录,生成的dll文件位于distrib目录下。
这样,Matlab的对外接口就设置好了。
2. VS2010开始引用Matlab接口
打开VS2010,使用C#环境(默认环境如何切换可以百度)。新建C#的控制台应用程序,命名为TestMatlabCs:
为此项目添加Matlab的接口引用(Preference)。需要添加三个,分别为MLApp(mlapp,tlb),MWArray(mwarray.dll),和新建立的sumab.dll,三个引用的添加过程类似。
首先添加MLApp。
在右侧的解决方案资源管理器中,右击引用,添加引用:
在弹出的对话框中,选择浏览选项卡,找到Matlab安装目录下的bin\win64目录(本例为D:\MATLAB\R2011b_x64\bin\win64),选择mlapp.tlb:
注:32位系统为bin\win32目录。
这样,就在项目的引用中,新添了MLApp的引用:
同理,再添加另外两个引用,路径分别为:
MWArray.dll:D:\MATLAB\R2011b_x64\toolbox\dotnetbuilder\bin\win64\v2.0
sumab.dll:D:\MATLAB\R2011b_x64\bin\sumab\distrib
下面,添加项目的测试代码。
目的是对两个变量a和b,调用matlab的sumab函数实现相加,输出结果。
打开项目的Program.cs文件。
首先,添加头文件引用:
using MathWorks.MATLAB.NET.Arrays;
在函数体的Main函数中,定义三个变量a、b、c,类型均为MWArray(matlab的对外矩阵类型接口),a赋初值为1,b赋初值为2,c用于存放结果。
MWArray a = 1, b = 2, c;
新建matlab接口sumab的类Sumab的实例,调用其方法sumab(),计算结果:
c = new sumab.Sumab().sumab(a, b);
这里偷了个懒,把建立实例并调用方法写在一块了。
将结果c转换成double类型,存储在double类型变量e中:
double e = (double)(MWNumericArray)c;
这里,需要了解一下double和MWArray的转换:
double <-> MWNumericArray <-> MWArray
所以,先将MWArray强制显式转换成MWNumericArray,在把MWNumericArray强制显式转换成double。
如上,转换优先级为从右向左,所以可以这样写在一块,也可以单独建立一个MWNumericArray变量,一步一步开始转换。
最后,将结果显示出来:
Console.WriteLine(e);
Console.ReadKey();
这时,如果直接运行,会报错误:
未能加载文件或程序集 “MWArray” 或它的某一个依赖项。。。
原因是,MWArray为64位Matlab对外接口,而VS当前使用的编译平台为32位,所以需要配置VS编译器为64位。
参考:http://www.ilovematlab.cn/thread-160339-1-1.html
点击VS工具栏Debug右侧的下三角,打开配置管理器:
在弹出的配置管理器对话框中,点击平台的右侧下拉三角,选择新建:
在弹出的新建项目平台中,选择新建平台为x64,从此处复制设置为<空>:
这样,就可以编译运行项目了。
Program.cs代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathWorks.MATLAB.NET.Arrays;
namespace TestMatlabCs
{
class Program
{
static void Main(string[] args)
{
MWArray a = 1, b = 2, c;
c = new sumab.Sumab().sumab(a, b);
double e = (double)(MWNumericArray)c;
Console.WriteLine(e);
Console.ReadKey();
}
}
}