关键词:MATLAB、C#、混合编程
1.问题描述
本例中,将MATLAB中的积分算法cumtrapz封装生成dll,用C#调用MATLAB的积分算法,实现MATLAB和.NET的混合编程,通过使用此方法将MATLAB函数封装成.NET中类的方法,这些类就可以像其他托管代码一样被.NET环境下的所有语言调用。
总体来讲,C#和MATLAB混合编程有以下优点:
1. MATLAB拥有大量的科学计算函数库,可以提供给C#直接使用,省去了开发这个过程。
2. MATLAB拥有自己的编译器和开发平台,而且语法简单,更容易使普通科研人员掌握。编写的m函数可以直接给C#使用,这就避免了重复开发。
3. MATLAB拥有大量的行业工具箱,如控制、图像处理,数学计算,可以很方便地开发各类专业程序。
2.解决方法
要实现C#调用MATLAB可以分为三步:
第一步:编写M函数,并在MATLAB中测试可以使用
第二步:在MATLAB中使用deploytool建立混编项目
第三步:C#中添加MATLAB的dll引用
第一步:编写M函数,并测试可以使用:
做一个简单的MATLAB算法的封装,只先将MATLAB的cumtrapz进行封装。首先在MATLAB中创建一个.m的文件,cumtrapz()函数输入time序列,在此次对比中,time为总时长为1秒钟,间隔为10us的timing。输入data序列,在此次对比中,data为被积分函数,即正弦函数。y为积分后的值,对值进行处理,赋值给Y。在调用时,只需使用integration(f,x,A),f为信号频率,x为采样率,A为幅值。源码如下,如图1所示:
function Y = integration(f,x,A)
value = linspace(0,1,x);
time = round(value,5);
data = zeros(1,x);
for i=1:1:x
data(i)=A*sin(2*pi*f*time(i));
end
y = cumtrapz(time,data);
value=mean(y);
Y = y-value;
end
图 1 Matlab中.m文件
注意,混编必须是m函数function的形式才能被调用。上述函数简单测试一下,没有问题(复杂的函数一定要多测试,否则后续调试非常困难)。继续下一步。
第二步:在MATLAB中使用deploytool建立混编项目
在MATLAB工作区输入命令:deploytool,然后在Compiler弹窗中选择Library Compiler,如下图2所示:
图 2 MATLAB Compiler弹窗
在对打包项目进行编辑的界面中,首先选择目标类型为“.NET Assembly”,然后添加刚才编写好的integration.m文件,在界面下方将默认的类名Class1修改为integrationTask,点击“保存”按钮,弹出保存工程,如图3所示,最后点击右上角的“Package”按钮执行打包过程。具体如下图4所示:
图 3 保存项目
图4 打包具体步骤
到此为止,打包完成,如图5所示,一个常规简单的Matlab.NET混编已经完成了60%了。打包完成后自动弹出文件夹,如下图6所示:
图 5 打包成功
图 6 生成的文件夹(包含dll文件)
第三步:C#中添加MATLAB的dll引用
打开VS2015创建一个窗体的应用程序,主要需要完成的是DLL的引用添加,将打包弹出文件夹中添加for_redistribution_files_only文件夹中的integration.dll
和D:SoftwareMatlab 2017a_Hezibuluo.comtoolboxdotnetbuilderbinwin64v4.0 (前边为MATLAB的安装路径)文件夹下的MWArray.dll添加到项目引用中去,如图7所示。其中MWArray主要的作用是做将MATLAB与C#中的数据进行转换交接。主要的原因是,MATLAB本身来说是一种比较松散的语言,在整个算法编程过程中并没有定义出来类似于C#中的多种数据类型,如double,float或者int等数据类型,所以在混个编程数据交接过程中需要有一个dll进行数据类型的转换的。
图 7 在VS中添加引用
同时需要添加以下的命名空间在系统中:
//用户自行添加的命名空间
using integration; //这是我们自己定义的
using standardValue; //这是我们自己定义的
using MathWorks.MATLAB.NET.Arrays; //在MWArray.dll中,最常用的
using MathWorks.MATLAB.NET.Utility; //在MWArray.dll中,最常用的
在使用过程中,我们可以这样理解,我们之前编译好的dll就是一个类,我们首先需要将这个类进行实例化,然后每一个我们编写好的.m文件都是一个方法。所以首先要做的就是将类进行实例化,整体的代码如下所示,利用MATLAB中的dll算法继续积分分析同时对积分后的数值解进行分析,其中单击buttonStart时的部分就是混合编程调用积分函数的部分:
namespace test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
#region Matlab
//对类进行实例化
IntergrationTask trapz = new IntergrationTask();
standardValueTask standardValue = new standardValueTask();
//调用integration方法(频率,采样率,幅值),返回结果
var result = trapz.integration(f, Fs, A);
var standardresult = standardValue.standardValue(f, Fs, A);
//将MATLAB的数据转化为中间过渡格式
MWNumericArray results = (MWNumericArray)result;
MWNumericArray standardresults = (MWNumericArray)standardresult;
//将中间过渡格式转化为C#的数据格式
double[,] value = (double[,])results.ToArray(MWArrayComponent.Real);
//积分标准值
double [,] sinestandardValue= (double[,])standardresults.ToArray(MWArrayComponent.Real);
double[] m_i = new double[(int)Fs];
double matlaberror =0;
for (int i = 0; i < m_i.Length; i++)
{
m_i[i] = value[0, i];
matlab_i[0, i] = sinestandardValue[0, i];//matlab_i第一列为积分解析解
matlab_i[1, i] = m_i[i];//matlab_i第二列为Matlab积分数值解
//differentValueAll[1,i] = m_i[i]-matlab_i[0, i] (数值解-解析解)
differentValueAll[1, i]= m_i[i] - matlab_i[0, i];
sum_m += (Math.Pow(differentValueAll[1, i], 2));
sum_standard_m += (Math.Pow(sinestandardValue[0, i], 2));
}
//积分误差为
matlaberror= Math.Sqrt(sum_m / sum_standard_m);
fre_error[1, frecount] = matlaberror;
textBoxMATLABError_i.Text = matlaberror.ToString();
#endregion
easyChartX_Mat_I.Plot(matlab_i, 0, dt);//将将二维积分数组画出 Matlab积分解析解与数值解
easyChartX_differentValue.Plot(differentValueAll, 0, dt);//画出积分误差值
f += frequencyGap;
}
easyChartXFrequency_Error.Plot(fre_error, 1000, frequencyGap);//Matlab积分误差值
}
测试结果如图8图9,混合编程的结果与MATLAB中的测试结果一定是一致的。
图 8 MATLAB中积分后的函数值
图 9 在VS中调用后生成的函数值
写在后面的话:
1. 混合编程虽然可以脱离MATLAB环境,但是必须安装MATLAB运行时—MCR,并且开发版本和运行版本的MCR要对应,否则会出错误,我们将在程序中进行说明。其中MCR安装是不需要版权的。
2.本来说做混合编程并不是一个比较复杂的事情,唯一的难点其实是在C#与MATLAB中数据转化的内容,其实这一部分在MATLAB自带的帮助文档是有写的。所以我们只需按照帮助文档的提示去操作就可以了。
3.混合编程过程中,有很多的问题都可以通过通用的搜索引擎中搜索答案,同时如果用MATLAB所生成的3D图形可以在C#中调用并且显示。
4.在相关链接中有一套非常好的C#与MATLAB混编的教学视频,非常推荐。
5.本此使用到了简仪的滤波器dll,所以要求.NET版本必须在4.6.2以上。
6.由于MATLAB是区分x64和x86的,因此在不同版本的MATLAB编译之后对应的C#管理器平台配置也需要选择对应的配置,如该实例是在x64平台下执行的。
http://www.cnblogs.com/eniac12/p/4390845.html
http://blog.csdn.net/qq_22033759/article/details/48122383
https://yq.aliyun.com/articles/26005
混合编程视频:
http://www.cnblogs.com/asxinyu/p/4288540.html#_label1
http://www.cnblogs.com/asxinyu/p/Bolg_Category_For_Matlab.html
Copyright © 2016-2025 JYTEK All Rights Reserved.