MATLAB与C++的接口问题.docx
《MATLAB与C++的接口问题.docx》由会员分享,可在线阅读,更多相关《MATLAB与C++的接口问题.docx(20页珍藏版)》请在冰豆网上搜索。
![MATLAB与C++的接口问题.docx](https://file1.bdocx.com/fileroot1/2023-7/12/569d0a1a-be04-4f8b-8347-4493662ae891/569d0a1a-be04-4f8b-8347-4493662ae8911.gif)
MATLAB与C++的接口问题
MATLAB是什么东东?
不用我多说了,大批的高手会告诉你它的无数好处。
但是MATL
AB程序存在的一般问题是:
1、运算速度较慢,特别是有fori=1:
?
?
?
forj=1:
?
?
?
......
end
end时,那你就死定了。
2、无法脱离MATLAB环境运行,虽然你可以用MATLAB自带的工具把M文件转成可执行程序,但是执行时,你只能看到一个黑黑的窗口,难道,这就是......Windows?
$%&%^$##%&。
3、GUI功能差。
许多大侠不愿意看到2中所述的DOS-Windows界面,于是使用了MATL
AB带的GUI生成工具。
(不要扔臭鸡蛋!
我知道你用GraphicEditor改了一下界面,发现以前的工作全都白做了——因为被覆盖了,西西)但是MATLAB提供的控件和事件实在有限。
GUI界面做好后放在机器里,向尚未进实验室的师妹(们)炫耀一下,还勉强可以增加一些魅力值。
如果被专家看到了,西西。
只怕效果不太美妙。
因此,如果能够实现MATLAB与VC或者BC或者C++BUILDER等可视化设计语言的交互,提高速度,美化界面,使程序更符合Windows的规范,同时又利用MATLAB的强大功能,对任何人来说都很有意义。
我在课题中涉及到了部分MATLAB与C++的接口知识,在这里总结出来,算是抛砖引玉
吧。
其中错误以及偏颇的地方,尚请各位大侠以及高手多多指教,谢谢!
(一)接口种类
用C++(或者C)语言操作MATLAB,有三种途径:
·MEX文件
在MATLAB中可调用的C或Fortran语言程序称为MEX文件。
MATLAB可以直接把MEX文件视为它的内建函数进行调用。
MEX文件是动态链接的子例程,MATLAB解释器可以自动载入并执行它。
MEX文件主要有以下用途:
对于大量现有的C或者Fortran程序可以无须改写成MATLAB专用的M文件格式而在MATLAB中执行。
对于那些MATLAB运算速度过慢的算法,可以用C或者Fortran语言编写以提高效率。
·MAT文件应用程序
MAT文件是MATLAB专用的用于保存数据至磁盘和向MATLAB导入、从MATLAB导出数据的
数据文件格式。
MAT文件提供了一种简便的机制,它允许你在两个平台之间以灵活的方式
移动数据。
而且,它还提供了一种途径来向其它单机MATLAB应用导入或者导出数据。
为了简化在MATLAB环境之外对MAT文件的使用,MATLAB给出了一个操作例程库,通过
它,我们可以使用C/C++或者Fortran程序读写MAT文件。
·引擎应用程序
MATLAB提供了一系列的例程使得别的程序可以调用MATLAB,从而把MATLAB用作一个计算引擎。
MATLAB引擎程序指的是那些通过管道(在UNIX系统中)或者ActiveX(在Windows系统中)与独立MATLAB进程进行通信的C/C++或者Fortran程序。
MATLAB同样提供了一个函数库来启动或者结束MATLAB进程、与MATLAB交换数据以及发送MATLAB命令。
(二)MEX文件
1、一个MEX的例子
#include"mex.h"
/*
*timestwo.c-examplefoundinAPIguide
*
*Computationalfunctionthattakesascalaranddoublesit.
*
*ThisisaMEX-fileforMATLAB.
*Copyright(c)1984-1998TheMathWorks,Inc.
*/
/*$Revision:
1.5$*/
/*本MEX文件的目的是实现timestwo的功能
voidtimestwo(doubley[],doublex[])是你的C++函数*/
voidtimestwo(doubley[],doublex[])
{
y[0]=2.0*x[0];
}
/*下面这个mexFunction的目的是使MATLAB知道如何调用这个timestwo函数*/
voidmexFunction(intnlhs,mxArray*plhs[],
intnrhs,constmxArray*prhs[])
/*nlhs是MATLAB命令行方式下输出参数的个数;
*plhs[]是MATLAB命令行方式下的输出参数;
nrhs是MATLAB命令行方式下输入参数的个数;
*prhs[]是MATLAB命令行方式下的输入参数;*/
{
double*x,*y;
intmrows,ncols;
/*Checkforpropernumberofarguments.*/
if(nrhs!
=1){
mexErrMsgTxt("Oneinputrequired.");
}elseif(nlhs>1){
mexErrMsgTxt("Toomanyoutputarguments");
}
/*在MATLAB命令行方式下,本MEX文件的调用格式是y=timestwo(x)
输入参数(x)个数=1,输出参数(y)个数=1,所以在程序一
开始就检查nrhs是否=1以及nlhs是否>1(因为MATLAB有一个缺省
输出参数ans,所以nlhs可以=0*/
输出参数ans,所以nlhs可以=0*/
/*Theinputmustbeanoncomplexscalardouble.*/
mrows=mxGetM(prhs[0]);/*获得输入矩阵的行数*/
ncols=mxGetN(prhs[0]);/*获得输入矩阵的列数*/
if(!
mxIsDouble(prhs[0])||mxIsComplex(prhs[0])||
!
(mrows==1&&ncols==1)){
mexErrMsgTxt("Inputmustbeanoncomplexscalardouble.");
}/*判断输入矩阵是否是double类,以及它是否只包括单个元素*/
/*为输出创佳一个矩阵,显然这个矩阵也应该是1x1的*/
plhs[0]=mxCreateDoubleMatrix(mrows,ncols,mxREAL);
/*获得指向输入/输出矩阵数据的指针*/
x=mxGetPr(prhs[0]);
y=mxGetPr(plhs[0]);
/*调用C++函数timestwo(y,x)*/
timestwo(y,x);
}
把上面这个文件用MEX编译后,MATLAB命令行下调用的实例
x=2;
y=timestwo(x)
y=
y=
4
2、MEX文件的编程规则
(1)编制自己的C++算法程序
(2)紧跟着定义mexFunction函数,mexFunction的定义法唯一:
它只能是如下形式:
voidmexFunction(intnlhs,mxArray*plhs[],
intnrhs,constmxArray*prhs[])
其名称和参数类型不许有任何改变,在mexFunciton函数中可以调用你刚定义好的C
++程序。
3、MEX文件的编译
MATLAB提供了专门编译MEX文件的工具:
mex,它可以把你做好的C++源程序编译成
.mex文件供MATLAB在命令行方式下调用。
调用时输入你的C++函数名(上例中为timestw
o)。
具体mex的设置和使用方法可以在MATLAB命令行方式下用helpmex命令获得。
(三)MAT文件
1、概述
.MAT文件是MATLAB专用的数据存储格式,由于MATLAB提供了一套可供MATLAB调用的
API函数集,所以我们完全可以在C++中访问.MAT文件。
这样做的意义是:
你可以把计算
过程留给MATLAB,而用C++对计算结果进行分析或者可视化处理。
2、接口
MATLAB提供的API函数集封装于下面两个标准DLL文件中:
libmat.dll,libmx.dll。
前者用于对MAT文件的操作,后者用于对MAT文件中矩阵的操作。
他们的存放路径为:
ATLAB>\bin。
在\extern\include中有与前面两个DLL对应的DEF文件:
libmat.edf,libmx.dbf。
其导出函数的原型位于同一目录下的
mat.h和matrix.h中
有了这些DLL、DEF、H文件,该怎么用C++调用API函数就不用我多说了吧。
3、MATLAB中常用的矩阵类型
·(复)双精度矩阵(ComplexDouble-PrecisionMatrices)
MATLAB中最常用的数据类型便是(复)双精度、非稀疏矩阵,这些矩阵的元素都是
双精度(double)的,矩阵的尺寸为m×n,其中m是总行数,m是总列数。
矩阵数据实际
存放在两个双精度向量中——一个向量存放的是数据的实部,另一个向量存放的是数据
的虚部。
指向这两个向量的指针一般被写做“pr”(pointertorealdata,指向实数
据的指针)和“pi”(pointertoimaginarydata,指向虚数据的指针)”。
如果一
个矩阵的pi为空的话,说明它是实双精度矩阵。
·稀疏矩阵(SparseMatrices)
MATLAB中稀疏矩阵的存储格式与众不同。
如同双精度矩阵一样,它拥有参数pr和pi
,同时它还具用三个附加的参数:
nzmax,ir以及jc。
nzmax是个整型数,其值为向量ir及pr、pi(如果存在的话)可能的最大长度。
它是
稀疏矩阵中不为零的元素的个数。
ir指向一个长度为nzmax的整型数阵列,阵列包含的是pr和pi中对应元素的行号。
jc指向一个长度为N+1的整型数阵列(N为矩阵的列数),其中包含的是列号信息。
对于任意的j,如果0≤j≥N-1,jc[j]是第j列中第一个非零项在ir、pr(以及pi)中的
序号,jc[j+1]-1是第j列最后一个非零项的序号。
因此jc[N]总等于nnz——矩阵中非零
项的总个数。
如果nnz小于nzmax,可以继续向矩阵中添加非零项而无需分配额外的存储
空间
。
4、主要函数举例:
·MATFile*matOpen(constchar*filename,constchar*mode)——打开/创建
·MATFile*matOpen(constchar*filename,constchar*mode)——打开/创建
一个MAT文件;
·intmatClose(MATFile*pMF)——关闭一个MAT文件;
·mxArray*mxCreateDoubleMatrix(intm,intn,mxComplexityflag)
——创建一个(复)双精度矩阵;
·mxArray*mxCreateSparse(intm,intn,intnzmax,mxComplexityflag)
——创建一个稀疏矩阵;
·mxArray*matGetNextArray(MATFile*pMF)——获得MAT文件里面下一个矩阵;
·constchar*mxGetName(constmxArray*pa)——获得矩阵pa的名称;
·voidmxSetName(mxArray*pa,constchar*s)——为矩阵pa设置一个名称;
·intmxGetM(constmxArray*pa)——获得矩阵pa的总行数;
·intmxGetN(constmxArray*pa)——获得矩阵pa的总列数;
·double*mxGetPr(constmxArray*pa)——获得矩阵pa的pr指针;
·int*mxGetIr(constmxArray*pa)——获得稀疏矩阵pa的ir指针;
·int*mxGetJc(constmxArray*pa)——获得稀疏矩阵pa的jc指针;
·intmatPutArray(MATFile*pMF,constmxArray*pA)
——把矩阵pA存储入MAT文件pMAF;
·voidmxDestroyArray(mxArray*pa)——释放矩阵pa(把它从内存中撤销);
5、两个例子:
·获取一个MAT文件中第一个矩阵的信息
·获取一个MAT文件中第一个矩阵的信息
typedefstruct{
charszFileName[256];
MATFile*pMatFile;
mxArray*pArray;
charszArrayName[64];
charszErrMsg[256];
unsignedintnArrayDim[2];
boolbIsSparse;
}MATFileStruct;
intGetMATFileStruct(MATFileStruct*pMAThdr)
{
if((pMAThdr->pMatFile=matOpen(pMAThdr->szFileName,"r"))==NULL)
{strcpy(pMAThdr->szErrMsg,"Can'topenthismatfile");
return(0);
}/*打开一个MAT文件*/
if((pMAThdr->pArray=matGetNextArray(pMAThdr->pMatFile))==NULL)
{strcpy(pMAThdr->szErrMsg,"Can'tgetarrays");
matClose(pMAThdr->pMatFile);
return(0);
}/*获取MAT文件中的第一个矩阵*/
}/*获取MAT文件中的第一个矩阵*/
pMAThdr->nArrayDim[0]=mxGetM(pMAThdr->pArray);/*获取其行数*/
pMAThdr->nArrayDim[1]=mxGetN(pMAThdr->pArray);/*获取其列数*/
strcpy(pMAThdr->szArrayName,mxGetName(pMAThdr->pArray));/*获取其名称*/
pMAThdr->bIsSparse=mxIsSparse(pMAThdr->pArray);/*判断它是否是系数矩阵*
/
mxDestroyArray(pMAThdr->pArray);/*在内存中撤销这个矩阵*/
matClose(pMAThdr->pMatFile);/*关闭MAT文件*/
return
(1);
}
·创建稀疏矩阵并赋值
inti,j,k,m,n,nzmax,*ir,*jc;
double*pr;
unsignedshort*pData;
mxArray*pa;file:
//初始化。
m=pLCMShdr->TrueHdr.nArrayDim[0];file:
//获得原矩阵行数。
n=pLCMShdr->TrueHdr.nArrayDim[1];file:
//获得原矩阵列数。
nzmax=0;
for(i=0;i{if(pData[i]!
=0)
nzmax++;
nzmax++;
}file:
//计算数据中非零元个数。
if(nzmaxnzmax=n;
pa=mxCreateSparse(m,n,nzmax,mxREAL);/*创建一个空的稀疏矩阵pa。
*/
mxSetName(pa,pLCMShdr->TrueHdr.szArrayName);/*为稀疏矩阵pa设置名称。
*/
pr=mxGetPr(pa);file:
//获得pa的pr指针。
ir=mxGetIr(pa);file:
//获得pa的ir指针。
jc=mxGetJc(pa);file:
//获得pa的jc指针。
k=0;
for(j=0;j{jc[j]=k;file:
//jc[j]:
截至到第j列非零元的个数。
for(i=0;i{if(pData[i]!
=0)file:
//如果第j列第i行的元素是个非零元。
{ir[k]=i;file:
//记录下第k个非零元的行号。
k++;
}
}
pData+=m;file:
//移动pData指针到下一列。
}
jc[n]=k;file:
//jc[n]等于矩阵中非零元的个数。
matPutArray(pmat,pa);file:
//把稀疏矩阵pa存入MAT文件pmat。
mxDestroyArray(pa);file:
//从内存中撤销矩阵pa。
(五)引擎应用程序
1、简介
引擎应用程序的实质是把MATLAB做为一个引擎,它允许从你自己的C++程序调用这个
引擎。
在运行时,引擎作为一个进程单独运行,你的C++程序也作为一个进程单独运行,二者可以通过进程间的通信机制进行交互。
2、引擎库
MATLAB引擎库包含了若干个控制MATLAB引擎的函数,如下所示:
engOpen启动MATLAB引擎
engClose关闭MATLAB引擎
engGetArray从MATLAB引擎中获取一个MATLAB矩阵
engPutArray向MATLAB引擎发送一个MATLAB矩阵
engEvalString执行于一个MATLAB命令
engOutputBuffer创建一个存储MATLAB文本输出的缓冲区
同时,引擎应用程序还可以使用前面提到的API函数。
3、一个例子
从这个示例中,我们看出引擎应用程序是如何编制的:
/*$Revision:
1.3$*/
/*
*engdemo.c
*
*Thisisasimpleprogramthatillustrateshowtocallthe
*MATLABenginefunctionsfromaCprogram.
*
*Copyright(c)1996-1998TheMathWorks,Inc.
*Allrightsreserved
*/
#include
#include
#include
#include"engine.h"
#defineBUFSIZE256
intmain()
{
Engine*ep;
mxArray*T=NULL,*result=NULL;
charbuffer[BUFSIZE];
doubletime[10]={0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,
8.0,9.0};
8.0,9.0};
6-6
/*
*StarttheMATLABenginelocallybyexecutingthestring
*"matlab".
*
*Tostartthesessiononaremotehost,usethenameof
*thehostasthestringratherthan\0
*
*Formorecomplicatedcases,useanystringwithwhitespace,
*andthatstringwillbeexecutedliterallytostartMATLAB.
*/
if(!
(ep=engOpen("\0"))){
fprintf(stderr,"\nCan'tstartMATLABengine\n");
returnEXIT_FAILURE;
}/*启动MATLAB引擎*/
/*
*PARTI
*
*Forthefirsthalfofthisdemonstration,wewillsenddata
*toMATLAB,analyzethedata,andplottheresult.
*/
/*
/*
*Createavariableforourdata.
*/
T=mxCreateDoubleMatrix(1,10,mxREAL);/*创建一个矩阵*/
mxSetName(T,"T");/*设置矩阵的名字为“T”*/
memcpy((void*)mxGetPr(T),(void*)time,sizeof(time));/*向矩阵“T”赋值
*/
/*
*把矩阵“T”置入MATLAB引擎
*/
engPutArray(ep,T)
/*
*Evaluateafunctionoftime,distance=(1/2)g.*t.^2
*(gistheaccelerationduetogravity).
*/
engEvalString(ep,"D=.5.*(–9.8).*T.^2;");/*执行MATLAB
命令:
D=.5.*(–9.8).*T.^2;*/
/*
*绘制图象.
*/
engEvalString(ep,"plot(T,D);");/*执行MATLAB命令:
绘图*/
engEvalString(ep,"title('Positionvs.Timeforafalling
object');");/*执行MATLAB命令:
给图象加标题*/
engEvalString(ep,"xlabel('Time(seconds)');");/*执行MATLAB命令:
设置X轴
坐标*/
engEvalString(ep,"xlabel('Time(seconds)');");/*执行MATLAB命令:
设置X轴
坐标*/
engEvalString(ep,"ylabel('Positi