首页 > 范文大全 > 正文

Visual C++调用MATLAB引擎的关键

开篇:润墨网以专业的文秘视角,为您筛选了一篇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.