Matlab和C混合编程的几种方法比较.docx
- 文档编号:29987006
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:23
- 大小:199.36KB
Matlab和C混合编程的几种方法比较.docx
《Matlab和C混合编程的几种方法比较.docx》由会员分享,可在线阅读,更多相关《Matlab和C混合编程的几种方法比较.docx(23页珍藏版)》请在冰豆网上搜索。
Matlab和C混合编程的几种方法比较
Matlab和C混合编程的几种方法比较
杨允军整理并调试
第一部分概述
Matlab是Mathworks公司于1982年推出的一套高性能的数值计算和可视化软件,到2005年已发行到R14(Matlab7.0),主流版本有4.0,5.3,6.1,6.5。
它是一种面向科学计算和数值分析的软件,涵盖了通信、短阵运算、图像处理、金融分析、模糊控制、自动控制、信号处理、系统仿真、微分计算等方面。
它提供了强大的科学运算、灵活的程序设计流程、高质量的数字图像处理等功能,突出的优点是强大的运算功能和近乎完美的绘图功能。
然而Matlab自身存在的一些不足使其在开发应用系统时受到局限,主要表现为以下几个方面:
(1)Matlab语言是一种解释执行的脚本语言,其程序运行效率低,特别是在编制大型复杂的应用系统时达不到理想的效果。
(2)Matlab编写的M文件是文本文件,很容易被直接读取,无法保护开发者的劳动成果。
(3)Matlab编写的程序只能在Matlab的平台下运行,不具备跨平台的能力,可移植性差。
(4)开发应用系统的界面能力差,很难做出友好的应用界面。
以上几点是VC等高级编程语言所专长的,而VC等高级编程语言在工程计算、复杂的数学计算、数字图形处理方面以及特定的学科领域的计算处理上远远不及Matlab。
因此将二者结合起来,各取所长,将能更好地满足实际应用中的需要。
为了实现混合编程,Matlab5.0以后的版本自带了C语言编译器(Compiler),可以将M文件转换为C—MEX或C/C++程序。
根据是否需要Matlab环境,一般将Matlab与VC++混合编程分为两大类:
Matlab在后台运行和可以脱离Matlab环境运行。
归纳起来Matlab与C接口有如下几种方法:
1.Matlab引擎(Engineer)采用客户/服务器的计算方式,通过Windows的ActiveX通道和Matlab相结合。
在具体的应用中,VC++的程序作为前端客户机,通过调用MatlabEngineer在后台与Matlab服务器建立连接,实现动态通信。
这种方法实现较为简单;不要求连接整个Matlab,只需要嵌入必要的MatlabEngineer库,可大大地节省系统资源,但这种Matlab在后台运行的效率低下。
2.Mideva(Matcom)是Mathtools公司推出的一种Matlab集成编译开发平台,提供对Matlab程序文件(M文件)的解释执行和开发环境支持。
经过简单设置后,Mideva可以将M源文件转换为C/C++,然后添加到MSVC、VB、C++Builder等的工程中。
自从Mathtools公司并入Mathworks公司以后,Matcom就停止了研发,最高版本为Matcom4.5。
3.利用Mideva直接生成EXE文件后,故C++中通过Shell调用,常见的外部函数有shellexec()或weinexec()。
这种方法简单方便,但运行时出现一个控制台窗口,而且由于VC和Matlab之间不能交互,且通用性差,仅适用于VC中调用Matlab,实现图形显示的场合。
4.借用C++编译器将Matlab下的M文件转换成DLL(动态链接库),其他应用程序可直接调用该DLL。
5.在C或者C++程序中使用Matlab提供的C/C++MathLibrary函数直接调用Matlab函数。
(没有尝试过)
6.按照Mideva的语法,在VC中直接书写Matlab语句实现Matlab与C的混合编程。
7.Add—in实现Matlab与VC的混合编程是Matlab6.0提供的一种最方便的方法,通过该方法,VC可直接在其开发环境中将M文件转换为CPP文件,并且可以现场修改M文件进行调试。
但是不知道为什么Matlab7.0取消了这种功能。
8.MAT文件方法,也就是将Matlab产生的数据,通过Matlab提供的一些函数,在VC中读取。
这种方法没有交互性可言。
以上几种方法各有利弊,方法1需要在安装有Matlab的环境中运行,可移植性差。
方法2、3、4、5、6、7可以脱离Matlab环境运行,移植性较好,但4、5、7好像不支持图形显示,而且不能编译Matlab的内建函数build-in函数(如fft、filter等)。
相对来说,Matcom的Add-in方法既简单功能又比较强大,但7.0以后的版本是否支持Matcom尚不得而知。
以上几种方法大同小异,除了MEX方法是在Matlab中调用C语言外,其他都是在VC中调用Matlab,后者是应用的主流。
这里举出几种典型的方法及应用实例,大体能满足工程中互相调用的需求。
几个实例都调试通过。
第二部分实例
2.1C-MEX实例
2.1.1引言
有时仅仅为了加快运算速度的需要,可以考虑用效率较高的C语言编写耗时大的部分,并且通过Matlab的API接口转化为C-MEX文件(在Windows系统中为DLL文件),和Matlab的普通函数一样调用。
周期谱理论是由W.A.Gardner等人深入研究并发展的[1],该理论的前提是认为信号具有周期平稳随机性,而大多数的通信信号符合这一特征。
周期谱理论在信号检测、分类、参数估计、同步、提取,尤其在低信噪比条件下可以取得满意的效果。
周期谱的工程计算分为时域平滑法和频域平滑法,后者是先求出信号的短时Fourier变换,然后作相关,存在计算量大的缺点,在Matlab实现过程中,这个缺点在数据量较大时是无法忍受的。
所以,找到一条能减小运算时间的途径是十分必要的。
Matlab是一种解释执行的语言,用向量代替循环是其推荐的方法,但当循环必不可少时,仅仅在Matlab环境内寻找优化途径就力不从心了,这时考虑从Matlab和其他高级语言的接口方面突破。
Matlab为了解决上述问题,提供了外部接口,本文主要介绍它与C/C++的接口。
Matlab提供了一种生成和调用C-MEX文件的技术,可以将m文件中耗时的代码用C实现,编译成动态库文件(Windows中为dll),使得其可以作为Matlab的build-in函数使用,这种C-MEX文件的执行效率比Matlab中的m函数要高。
C-MEX文件的另一个优势是调试方便,可以在Matlab或借用VC环境进行调试。
当然,Matlab还提供了其它一些技术,如Mat文件、引擎方式、m文件编译成动态库在VC中调用等。
Mat文件只能传递变量数据,应用有限;引擎方式在程序运行时启用Matlab,慢且不方便;m文件通过Matlab的mcc编译器编译成动态库在VC中调用的方式相对来说完美,但也存在调用动态库时语法复杂的缺点。
本文介绍的C-MEX文件的方法接口简单、调用方便,可以大幅度减小周期谱的计算时间。
2.1.2原理
C-MEX文件其实就是带有Matlab接口的C文件编译好的动态连接库,程序主要由两部分组成:
计算子程序和接口子程序[2][3]。
前者包含了用于计算的源代码,用来完成实际的计算工作,用C语言实现;后者它是计算子例行程序同Matlab环境之间的接口,用来完成两者之间的通信任务。
接口子例行程序的名称固定为mexFunction,该函数中以mx、mex开头的函数是Matlab与C的接口函数,mx-函数用来对mxArray结构体类型的操作,mex-函数用来对外传递数据。
mexFunction函数有四个参数,分别为prhs、nrhs、plhs和nlhs,其中prhs为一个mxArray结构体类型的指针数组,该数组的数组元素按顺序指向所有的输入参数;nrhs为int类型,用以表示输入参数的个数;plhs也是一个mxArray结构体类型的指针数组,该数组的数组元素按顺序指向所有的输出参数;nlhs为int类型,表示输出参数的个数。
以上两个部分是典型的C-MEX文件格式,其工作原理如图1所示。
为了能够在Matlab环境下运行这个程序,必须首先配置MEX的编译环境,其配置工作可在Matlab命令窗口中运行mex–setup,会提示选择编译器
[1]LccCversion2.4inD:
\MATLAB6P5\sys\lcc
[2]MicrosoftVisualC/C++version6.0inD:
\ProgramFiles\MicrosoftVisualStudio
选择Compiler:
MicrosoftVisualC/C++6.0,就可以在Matlab或者VC环境输入C代码,编译生成C-MEX文件了,接下来介绍C-MEX文件的建立和调试。
2.1.3实现过程
Matlab中调试MEX文件的错误提示信息不容易理解,在VC中调试可以有效地解决这方面的问题,这里介绍VC环境下编译生成及调试MEX文件的过程。
(一)建立dll工程。
在VC中创建DLL工程SCFdll,在def文件中输入LIBRARYSCFdll,EXPORTSmexFunction,表示库文件名或者对外发布的包装为SCFdll。
(二)建立C文件,写运算子程序部分和接口子程序部分。
新建CSource文件,加入#include"mex.h"语句,该头文件在目录
因为用到了VC的编译器,所以在lib搜索路径中还要加入
在周期谱计算中,我们发现谱相关运算消耗了大量的时间,用C-MEX文件代替这一部分Matlab代码可以大幅度减少耗时。
C文件的计算子程序用来完成短时Fourier变换后的相关计算,doubleSpecR[]为短时Fourier变换的实部,doubleSpecI[]为短时Fourier变换的虚部,DatLen为短时Fourier变换的长度,doubleSR[]为得到的周期谱的实部,doubleSI[]为得到的周期谱的虚部,N1为搜索带宽的起点,N2为终点,M为平滑次数。
代码如下:
/*-----C++源程序-----*/
voidspec_smth(doubleSR[],doubleSI[],doubleSpecR[],doubleSpecI[],
intM,intN1,intN2,intDatLen)
{
inti,v;
doubletempR,tempI;
intN=N2-N1;
v=0;
for(i=0;i { SR[i]=0; SI[i]=0; } for(v=0;v for(i=0;i { SR[i]=SR[i]+SpecR[v+i+N1]*SpecR[v-i-N1+DatLen]+SpecI[v+i+N1]*SpecI[v-i-N1+DatLen]; SI[i]=SI[i]+SpecR[v-i-N1+DatLen]*SpecI[v+i+N1]-SpecR[v+i+N1]*SpecI[v-i-N1+DatLen]; } } C文件的接口子程序mexFunction用来完成C语言和Matlab的数据交换,一般用来检验输入输出参数和调用计算子程序。 代码如下: /*-----接口子程序-----*/ voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[]) { intM; intDatLen; intN1; intN2; intN; double*SR; double*SI; double*SpecR; double*SpecI; /*Checkforpropernumberofarguments*/ /*if(nrhs! =5) mexErrMsgTxt("Fiveinputsrequired.");//mexErrMsgTxtbreaksyououtoftheMEX-file. if(nlhs! =2) mexErrMsgTxt("Twooutputsrequired."); if(mxGetN(prhs[0])! =mxGetN(prhs[1])) mexErrMsgTxt("IandQmustbethesamesize."); */ /*Distributetheparameters*/ DatLen=mxGetN(prhs[0])/2;/*Thespectrumiscyclo-spread*/ M=mxGetScalar(prhs[2]); N1=mxGetScalar(prhs[3]); N2=mxGetScalar(prhs[4]); N=N2-N1; /*Assignpointerstothevariousparameters*/ SpecR=mxGetPr(prhs[0]); SpecI=mxGetPr(prhs[1]); plhs[0]=mxCreateDoubleMatrix(1,N,mxREAL);//mallocspace SR=mxGetPr(plhs[0]);//spectrumforoutput plhs[1]=mxCreateDoubleMatrix(1,N,mxREAL);//mallocspace SI=mxGetPr(plhs[1]);//spectrumforoutput spec_smth(SR,SI,SpecR,SpecI,M,N1,N2,DatLen); } (三)设置matlab.exe为调试环境和路径。 Projects->Settings->Debug的Executabledebugsession中选择matlab.exe作为Debug环境。 按F7编译通过后,按F5运行,此时就会自动启动Matlab环境,将SCFdll当成普通函数,在Matlab命令窗口中输入数据STFT,Len和命令SCF=SCFdll(STFT,Len)进行验证。 当然,C-MEX文件SCFdll.dll必须在Matlab的搜索路径中。 还可以在C文件中设置断点,这为调试带来了很大的方便。 因为生成的C-MEX文件最终是在Matlab中作为build-in函数运行,和普通函数没有区别。 2.1.4总结 测试选取的硬件条件为赛扬2.4,运行环境为Matlab6.5,用两种不同的计算方法对不同长度的数据点的周期谱计算进行了计算时间的测试,测试结果如下表。 可以看出,C-MEX对周期谱计算进行优化的效果是明显的,在本文描述的算法中可以将计算时间缩短为用m函数直接计算耗时的1/7左右。 表一m函数直接计算和C-MEX优化计算耗时比较(单位: 秒) 数据点数 32k 64k 128k 256k 512k m函数计算 1.0780 3.5000 13.4210 84.1720 354.6710 C-MEX计算 0.1870 0.8280 2.7970 12.5470 47.5160 2.2Add-in实例 2.2.1引言 在众多的Matlab与VC结合的方法中,Add-in方法简单,结构明了。 能在没有Matlab环境的情况下(配置过程需要用到Matlab环境),将M文件转化为C++文件,从而方便地在VC中调用,Add-in还提供打包功能,自动提取库文件,打包成zip文件后,在没有安装Matlab的机子上解压缩,从而脱离Matlab环境。 更重要的是,可以边修改m文件边调试,至于书上介绍的用MatrixView观察变量的做法,我没能实现,遗憾。 但是VC的编译器不能编译Matlab的内建函数的硬伤使得对很多算法的编译不能得心应手,比如该编译器对FFT就无能为力。 滤波器设计是信号处理、自动控制等领域不可回避的问题,用VC等工具实现滤波器的设计相当繁琐,Matlab在这些方面又得天独厚的优势,所以可以考虑在VC中调用Matlab的滤波器设计工具箱,在VC中直接实现滤波器的设计。 2.2.2原理 Add-in的原理是将M文件转化为C++文件,经过适当的Matlab的MathC函数连接整合,在VC中调用。 2.2.3实现过程 VC中Add-in的设置步骤: (1)在Matlab命令行中键入mex–setup(注意“mex”与“-”之间有空格)和mbuild-setup命令,按照给出的提示选择MSVC6.0作为编译器。 配置好后,Matlab将提示Add-in组件已成功安装到VC。 此时别忘了在Matlab命令行中继续键入cd(prefdir)和mccsavepath命令,将Matlab的路径写入VC中的某些文件。 (2)在VC菜单中选择Tools->Customize->Add-insandMacroFiles一栏,勾选MATLABAdd-in,然后关闭,此时下图所示的Matlabadd-in的工具条Toolbar1就会出现。 (3)接下来是在VC的include设置搜索路径。 在Tools->Options->Directories的include搜索路径中添加 前期准备到这里就完成了,配置一次,终身管用。 下面用Add-in方法,调用Matlab的滤波器设计工具箱,做一个简单的低通滤波器设计。 具体步骤如下: 首先建立一个基于对话框的exe工程取名test2,修改对话框的界面如图: N为滤波器的阶数,WN是归一化带宽,产生的滤波器系数在Filtercoefficients编辑框内显示出来。 第二步是点击Toolbar1内的.m++,选择添加myfilter.m文件,源代码如下: function[b,a]=myfilter(n,wn) [b,a]=butter(n,wn); 此时出现下图所示的对话框,选择默认,按OK后,自动生成一大堆的m文件和C源和.h文件,有用的是myfilter.c和myfilter.h。 前者是myfilter.m转化而来的C文件,不过太繁琐,只要看后者就可以知道他的功能和调用方法了。 myfilter.h文件里有这几行语句: externvoidInitializeModule_myfilter(void); externvoidTerminateModule_myfilter(void); extern_mexLocalFunctionTable_local_function_table_myfilter; externmxArray*mlfMyfilter(mxArray**a,mxArray*n,mxArray*wn); externvoidmlxMyfilter(intnlhs,mxArray*plhs[],intnrhs,mxArray*prhs[]); 其中externvoidInitializeModule_myfilter(void);和externvoidTerminateModule_myfilter(void);明显是初始化语句,externmxArray*mlfMyfilter(mxArray**a,mxArray*n,mxArray*wn);为调用形式,具体实现在myfilter.h文件中,能把人看晕。 第三步为Test按钮的响应函数voidCTest2Dlg: : OnButtonTest()添加代码: doublenOrder;//Â˲¨Æ÷½×Êý doublenWn;//Â˲¨Æ÷½ØֹƵÂÊ(0~1) double*pNum=NULL;//ÓÃÀ´·µ»ØÂ˲¨Æ÷ϵÊý mxArray*mxArray_nOrder;//mxArrayÀàÐ͵ÄÂ˲¨Æ÷½×Êý mxArray*mxArray_nWn;//mxArrayÀàÐ͵ÄÂ˲¨Æ÷½ØֹƵÂÊ mxArray*mxArray_num;//mxArrayÀàÐ͵ÄÂ˲¨Æ÷ϵÊý UpdateData(true); nOrder=double(m_EditN); nWn=m_EditWN; mxArray_nOrder=mxCreateDoubleScalar(nOrder);//mxArray_nOrder³õʼ»¯ mxArray_nWn=mxCreateDoubleScalar(nWn);//mxArray_nWn³õʼ»¯ InitializeModule_myfilter();//µ÷Óóõʼ»¯ mxArray_num=mlfMyfilter(NULL,mxArray_nOrder,mxArray_nWn);//º¯Êýµ÷Óà pNum=mxGetPr(mxArray_num);//doubleÀàÐ͵ÄÂ˲¨Æ÷ϵÊý TerminateModule_myfilter();//µ÷ÓÃmlfMyfilterÍê±Ï mxDestroyArray(mxArray_nOrder); mxDestroyArray(mxArray_nWn); mxDestroyArray(mxArray_num); mxCreateDoubleScalar、mxGetPr、mxDestroyArray等函数功能可以在Matlab的帮助了找到。 代码层次分明: mxArray_nWn=mxCreateDoubleScalar(nWn);之前的语句用来实现参数的输入;mxArray_num=mlfMyfilter(NULL,mxArray_nOrder,mxArray_nWn)完成滤波器的设计;pNum=mxGetPr(mxArray_num);接收滤波器的系数,最终的滤波器系数保存在指针pNum中,能在VC中使用。 至于在实际应用中具体怎么操作,已不在讨论范围之内了。 2.2.4总结 1.可以边修改m文件边调试; 2.点击Toolbar1上的包裹状按钮还可以实现程序的打包,将用到的一些库文件发布成一个压缩文件,在没有安装Matlab的机子上,解压缩,程序照样可以运行,这一点很有诱惑力; 3.不能编译Matlab的内建函数,图形句柄不能用(不知道是我没调通还是真的不能用)。 总体来讲,这种方法还是值得推荐的。 2.3Matcom实例 2.3.1引言 Matcom的特点: Matcom是一个非常有用的m文件编译器(compiler),它有如下几大优点: 1.它提供了Matlab语言中m文件和其他语言的接口,使m文
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Matlab 混合 编程 方法 比较