开篇:润墨网以专业的文秘视角,为您筛选了一篇Visual C++调用MATLAB引擎的关键范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!
摘要: 针对visual c++调用matlab引擎进行协同分析时出现的许多难以预料的编程方面的问题,通过对微分方程的求解来介绍编程的方法以及该注意的事项,减少编程者在编程时遇到的问题,提高对这两个软件协同分析的理解。
Abstract: For solving the problem in programming by using Visual C++ to call for MATLAB engine,through the solution of differential equations to describe programming methods and to reduce the programming problems and improve the understanding of the two softwares.
关键词: Visual C++;MATLAB;协同分析
Key words: Visual C++;MATLAB;collaborative analysis
中图分类号:TP311文献标识码:A文章编号:1006-4311(2010)16-0161-02
0引言
MATLAB引擎是MATLAB提供的一组编程接口,通过引擎,其他编程环境(如VC++)可以使用MATLAB提供的计算和图形功能。使用引擎与VC++连接,可以充分发挥VC++在界面编写以及硬件访问等方面的优势,而比较复杂的信号处理、计算等任务则交由MATLAB完成,而运算结果可以交由VC++6.0继续使用。对于那些实时性要求不高,而数据处理任务较重的场合,使用MATLAB引擎确是一个比较好的方法。
1调用MATLAB引擎的关键
要实现Visual C++调用MATLAB引擎进行混合编程,需要几个MATLAB库:libeng.lib、libmx.lib、libmat.lib。这些库文件要通过动态链接库libeng.dll、libmx.dll、libmat.dll生成,它们存在于MATLAB\extern\include目录下。
1.1 Visual C++编译环境设定启动Visual C++6.0集成环境,建立MFC AppWizard类型工程。在项目工程建好后,在该项目的菜单栏中选择Tool|Options菜单,打开Options窗口,选择Directories选项,在Show directories for下拉菜单中选择Include files,添加MATLAB中的includes文件夹(如D:\MATLAB7\EXTERN\INCLUDE);在Shw directories for下拉菜单中选择Library files,添加MATLAB中的文件夹msvc60(如D:\MATLAB7\EXTERN\LIB\WIN32\MICROSOFT\MSV C60)。
1.2 在VC++工程中加入lib文件选择Projict|Setting菜单,打开项目设置窗口,单击Link选项,在Object/Library modules文本框中添加libmx.lib libeng.lib libmat.lib,并在含类的cpp文件开头加入engine.h文件。
1.3 在VC++中调用MATLAB引擎实现VC与MATLAB之间的协作分析,需要在VC中调用MATLAB引擎。MATLAB引擎的操作是通过启动一个独立于应用程序的进程来实现的。在Windows环境下,应用程序通过组建对象模型(COM)接口与MATLAB进行通信。
MATLAB提供了一个函数库来实现对MATLAB的控制,这个函数库实现的功能主要有:①启动和结束MATLAB进程;③从MATLAB发送和接收数据;③向MATLAB发送命令。
与其他的接口相比,引擎提供的MATLAB功能支持是最全面的,它可以完成任何计算和绘图操作,对所有的数据结构提供完全支持。
表1为引擎库函数及其功能,它可用耒启动MATLAB引擎、完成数据传输及处理等任务。
2实例解析
设k1=28396N/mm,k2=86606N/mm,k3=123N/mm,m2=12450kg,v0=208.33mm/s,m1=23003kg,m3=26000kg。求解微分方程组
m00 m+k+k -k-k k+kxx= 0-kvt
当t=0时有:x(0)=(0)=0x(0)=(0)=0,并且满足:k(vt+x+x)=mg的解x、x及t,并以txt文档的形式输出。
2.1 按新建工程向导新建工程文件DemoDiffMatlab的对话框。
2.2 添加“微分方程组求解”和“导出数据”控件,如图1所示。
2.3 在VC++工程中加入lib文件,并在对话框类DemoDiffMatlabDlg开头加入engine.h头文件。
2.4 双击“求解微分方程”控件,并添加响应函数。
void CDemoDiffMatlabDlg::OnDiffMatlab()
{
double VC_k[3]={28396,86606,123}, v0=208.33, VC_m[3]={23003,12450,26000};
mxArray *VC_Matlab_m=NULL,*VC_Matlab_k=NULL,*VC
_Matlab_v;
if(!(ep=engOpen(NULL)))//打开Matlab引擎
MessageBox("Can't start the MATLAB engine","引擎打开失败!");
VC_Matlab_m=mxCreateDoubleMatrix(1, 3, mxREAL);//创建1维3列MATLAB矩阵
//把VC_m数组赋值给刚创建的MATLAB矩阵,在赋值时VC_m给出的应是存储数据的地址而不是内容
memcpy((char*)mxGetPr(VC_Matlab_m),(char*)VC_m,3*sizeof(double));
//将VC_Matlab_m矩阵传输到MATLAB中,并以变量名为Matlab_m进行保存,变量v0和VC_k的传输方式于此一样,这里省略。它们在MATLAB引擎中的变量名分别为Matlab_k和Matlab_v
engPutVariable(ep,"Matlab_m",VC_Matlab_m);
//利用MATLAB引擎库的字符串传递函数进行求解,为了求解方便,这里利用中间变量
engEvalString(ep,"a1=1000*(Matlab_k(1)+Matlab_k(2))/Matlab_m(1);a2=1000*Matlab_k(2)/Matlab_m(1);a3=1000*Matlab_k(2)/Matlab_m(2);a4=1000*(Matlab_k(2)+Matlab_k(3))/Matlab_m(2);a5=1000*Matlab_k(3)*Matlab_v/Matlab_m(2);t0=sym('t0');");
//用s=dsolve('D2f=-a1*f+a2*g','D2g=a3*f-a4*g-a5*t0')来解微分方程,并给与初始值
engEvalString(ep,"s=dsolve('D2f=-a1*f+a2*g','D2g=a3*f-a4*g-a5*t0','f(0)=0','g(0)=0','Df(0)=0','Dg(0)=0','t0');");
//利用dsolve()函数得出来的结果是字符型表达式,应把它转换成数据类型的表达式,用eval()可以实现。该函数是MATLAB里很重要的一个函数,且只用用VC++调用MATLAB引擎才能使用该函数,其他方法不行。
engEvalString(ep,"xx10=eval(s.f);xx20=eval(s.g);");//将转换后的结构暂存到xx10和xx20里
//利用附加条件将t0解出,利用solve()函数可以解决一元函数的求解
engEvalString(ep,"f=Matlab_v*t0+xx10+xx20-Matlab_m(3)*9.8/Matlab_k(3);");
engEvalString(ep,"t0=solve(f);");
engEvalString(ep,"x10=eval(s.f);x20=eval(s.g);i=0;x10=eval(x10);x20=eval(x20);t0=eval(t0);");
}
2.5 双击“导出数据”控件,并添加响应函数。
void CDemoDiffMatlabDlg::OnOutPutData()
{ mxArray *VC_Matlab_x10=NULL,*VC_Matlab_x20=NULL,*VC_Matlab_t=NULL;
double *VC_x[2],*VC_t[1];
char cVC_x1[30]="",cVC_x2[30]="",cVC_t[30]="";
//将MATLAB引擎中的数据x10赋值给mxArray类型的矩阵,该类型矩阵是MATLAB数据到VC++的中介
VC_Matlab_x10= engGetVariable(ep, "x10");
//每执行一次数据传输,通过以下的判断语句才能正确的将MATLAB数据传输到VC++中,这是由于在使用指针的时候,VC++直接和内存的地址打交道,对于相邻或相近的地址可能会出现问题。使用判断语句能够使连续两次数据传输的地址离得较远,从而避免了数据传输错误。x20和t0的数据传输方式于此一样,这里省略。
if (VC_Matlab_x10 == NULL)
{MessageBox ((LPSTR)"Get Array Failed", (LPSTR)"数据转换失败!");}
//把mxArray类型数据转换成double型数据,
else {VC_x[0] = mxGetPr(VC_Matlab_x10);
//在VC++中把获取到的数据转成字符型,以备数据输出。
if (*VC_x[0]){sprintf(cVC_x1,"%gmm",*VC_x[0]);}
else MessageBox ((LPSTR)"Error!", (LPSTR)"字符串转换失败!");
//在每次数据传输结束,都应该把mxArray阵列从内存中消去,以减少内存
mxDestroyArray(VC_Matlab_x10);
}
//输出数据并保存到“数据输出.txt”文档里
fstream file("数据输出.txt",ios::out|ios::trunc);
if(!file){MessageBox("数据输出.txt不能创建!","创建文档失败!");return;}
//向该文档写入数据
file.write(cVC_x1,strlen(cVC_x1));
file.write(cVC_x2,strlen(cVC_x2));
file.write(cVC_t,strlen(cVC_t));
}
2.6 运行程序在VC++中生成可执行文件DemoDiffMatlab.exe,运行程序。先进行微分方程的求解,然后把数据导出,导出的数据如图2所示。
3结束语
通过MATLAB与VC++的接口技术,在VC++中调用MATLAB引擎求解微分方程组,实现了MATLAB的可视化操作,这种方法极大的提高程序开发效率,缩短了开发周期,同时也有利于提高软件质量,是实现工程自动分析的关键技术。
本文中对实例编程的详细讲解,能够使其他编程者少走弯路,同时也能促进初学者对这两个软件协作的理解,具有一定的学习指导价值。
参考文献:
[1]MATLAB7.0 Help 2004./.
[2]郑阿奇.Visual C++实用程序设计.第3版.北京:电子工业出版社,2007.
[3]苏金明,黄国明,刘波.MATLAB与外部程序接口.北京:电子工业出版社,2004.
[4]张平.MATLAB基础与应用简明教程.北京:北京航空航天大学出版社,2001.