VC++与MATLAB混合编程的实现方法

时间:2022-06-16 03:27:57

VC++与MATLAB混合编程的实现方法

摘要:在科学研究和工程应用中,科研工作人员往往需要首先提出一种新算法;然后在相应的仿真工具里面进行仿真验证,如果仿真验证错误,则应该重新对算法进行修正,并再次进行仿真验证,直到仿真验证通过,此时可以确保算法在理论原理上的正确性。文章介绍了采用VisualC++与MATLAB进行混合编程的重要特点和意义,重点阐述了三种不同的VisualC++与MATLAB混合编程的方法,并对这三种方法做了全面的分析比较和总结。

关键词:VC++;MATLAB;MATCOM;混合编程;编译器

中图分类号:TP311 文献标识码:A 文章编号:1009-2374(2010)09-0013-04

一、VC++与MATLAB混合编程的实现方法概述

在科学研究和工程应用中,科研工作人员往往需要首先提出一种新算法;然后在相应的仿真工具里面进行仿真验证,如果仿真验证错误,则应该重新对算法进行修正,并再次进行仿真验证,直到仿真验证通过,此时可以确保算法在理论原理上的正确性,但是其实际性能还有待进一步验证;接下来在相应的实际工程开发环境下实现算法,测试算法的各项性能指标是否符合技术指标要求,若不满足,则应当改进算法,并再次投入到前面的仿真验证阶段,直至算法的各项性能指标满足要求,或在某种前提条件及评价标准下算法总体性能指标最优。上述的整个过程如图1所示:

在仿真验证阶段,目前的主要仿真工具普遍采用MATLAB。MATLAB是Math Works公司推出的数学软件,它将数值分析,矩阵计算,信号处理和图形显示结合在一起,包含大量高度集成的函数可供调用,命令语句功能十分强大,为科学研究、工程设计及众多学科领域提供了一种简洁,高效的编程工具。然而MATLAB并非标准的编译链接语言,而是一种解释性语言,这就大大限制了其代码的执行速度,并且源代码的公开不利于算法和数据的保密,局限于MATLAB运行环境,不能用于开发商用软件。与此相反,C/C++环境下通过编译链接后的目标代码质量高,程序执行效率高,还具有良好的不同平台可移植性,所以工程开发时常常需要将已经验证通过的算法在C/C++环境下实现。可见,为了提高研发效率有必要使用MATLAB和C/C++混合编程。不过这里就存在重复编码的问题。也就是说,同样的算法要在MATLAB和C/C++环境下各写一次代码,增加了不必要的工作。因此这样就很自然的提出了一个关于如何把现有的已经通过仿真验证的m文件自动转换为符合工程实践要求的C/C++文件的问题。下面将介绍三种不同的方法:

二、采用MATLAB自带编译器mcc

从MATLAB5 1版本开始,Math Works公司推出了一系列的MATLAB自带编译器来解决MATLAB与C/C++的接口问题。编译器mcc可以将MATLAB的C/C++数学库编译为VC++编译器能识别的代码嵌入VC++环境。mcc是一种调用MATLAB编译器的命令,它既可以在MATLAB命令行方式下使用,也可以在DOS或者是UNIX命令行方式下使用。值得注意的一点是,由于mcc编译器本身无法编译脚本文件,因此,需要将脚本文件改写成函数文件,也就是说在原始脚本文件的前端,加一行使用关键字function定义的函数即可。

在使用mcc命令实现MATLAB中的m函数文件自动转化为C/C++文件时,首先将要调用的函数在MATLAB中写成m文件,然后使用mcc命令将m文件编译成可以在VC++中调用的cpp文件,最后在VC++程序中调用执行。也可以用mcc编译器将m文件编译成为stand-alone程序。

mcc编译器把m文件转换成相应的C/C++文件时提供了不同种类命令参数以便控制输出不同的文件。

-x可以把m文件转换为C文件并且创建相应的能直接在MATLIB中调用的CMEX-file文件。

-S可以把m文件转换为C文件并且创建相应的使用动态大小输入输出的SimulinkS-function。

-m可以把m文件转换为C文件并且创建独立于MATLAB环境运行的独立可执行文件。

-p可以把m文件转换为C++文件并且创建独立于MATLAB环境运行的独立可执行文件。

-Bsgl可以把包含调用绘图函数的m文件转换为C文件并且创建独立于MATLAB环境运行的独立可执行文件(需要独立图形库SGL)。

-Bsglcpp可以把包含调用绘图函数的m文件转换为C++文件并且创建独立于MATLAB环境运行的独立可执行文件(需要独立图形库SGL)。

-Bpcode可以把m文件转换为MATLAB的p文件。

此外,-W,-T等参数来控制生成C/C++的库文件或者共享库文件。如果需要调试,可以加上-g参数。

例如在MATLAB的命令行方式下采用如下命令mcc-Bsglcppmyfile。m将可以得到myfile.cpp,myfile.hpp,myfile_mainhg.cpp,myfile.exe等几个文件。其中myfile.exe已经是一个可以独立MATLAB环境运行的可执行文件。而myfile.cpp,myfile.hpp,myfile_mainhg.cpp三个文件可以在VC++的开发环境下调用。

通过使用上述mcc命令可以把算法在MATLAB中实现并且转换出相应的C/C++文件,那么接下来可以在VC++环境中方便的设计程序界面,并调用生成的C/C++文件中的模块。在VC++工程中需要注意以下几点:

1.加入需要包含的头文件所在的文件夹。通过菜单项Tools选择Options,在弹出来的Options模式设置对话框中选择Directories选项卡,在Showdirectoriesfor下拉框中选择Includefiles,在下面的Directories列表中添加两项:%MATLAB%\extern\include和%MATLAB%\extern\include\cpp。

2.加入需要引用的库文件所在的文件夹。在Show directories for下拉框中选择Library files,在下面的Directories列表中添加两项:%MATLAB%\extern\lib\win32和%MATLAB%\extern\lib\win32\microsoft\msvc60。

3.加入需要引用的动态链接文件所在的文件夹。在Show directories for下拉框中选择Execu table files,在下面的Directories列表中添加%MATLAB%\bin\win32一项。

4.在工程中加入需要引用的库文件。通过菜单项Project选择Settings,在弹出来的ProjectSettings模式设置对话框中选择Link选项卡,在Object/librarymodules下面的编辑框中添加工程需要的库文件:libmatpm.lib,libmatlbmx.lib,libmatlb.lib,libmx.lib,sgl.lib,libmwsglm.lib,libmmfile.lib,libmat.lib。同时,在ProjectSettings模式设置对话框中的General选项卡中的Microsoft Foundation Classes的下拉框中选择Use MFC in a Shared DLL,使用动态的MFC类库。

通过上述方法,采用VC++调用mcc命令生成的C/C++文件的方法进行程序设计与单独采用VC++相比从编程复杂程度来说有明显的降低。

三、利用MATCOM转化

MATCOM是MathTools公司(现已被MathWorks公司收购)开发的为MATLAB中的m文件进行高效解释和调试的集成开发环境,其最高版本为4.5。集成调试编译环境为MIDEVA。通过MATCOM连接MATLABm文件有以下三种方法:

1.经过简单的设置,在MIDEVA中打开需要转换的m源文件,选择File菜单项下面的compile to exe or dll,将m源文件转换为C/C++文件。在MATCOM的DEBUG目录下可以找到生成的h,cpp,exe等文件。然后添加需要的C/C++文件到MSVC工程中,再包含头文件就可以实现调用。

2.由MIDEVA直接生成EXE文件,然后在VC中通过Shell调用。这种方法简单方便,但运行时出现一个控制台窗口,而且由于VC++和MATLAB之间不能交互,通用性差,一般而言仅适用于VC++调用MATLAB实现图形显示的场合。

3.通过Visual MATCOM工具条,使用Add-in,这种方法提供了MATLAB和VC++直接集成的途径,且可快速集成m文件到VC++工程中创建独立的C/C++应用程序,CMEXDLL,在调试过程中可以查看矩阵变量的值,可直接修改m源文件而不用修改生成的C/C++文件,极大的方便开发人员,让开发人员把主要精力放在算法的构造和设计方面。

一般采用第三种方法,这需要在VC++环境中安装Visual MATCOM工具条。在VC++环境中选择主菜单中Tools菜单项,在下拉菜单中选择Customize,此时回弹出Customize对话模式框,选择其中的Add-ins and Macro Files选项卡,选择Browse按钮,改变文件类型为Add-in(.dll),选择%MATcom45%\bin\mvcide.dll文件,最后点击确定。这时就在VC++的开发环境中安装好了Visual MATCOM工具条。下面简要介绍一下如何在VC++环境中调用MATCOM生成的C/C++模块:

首先在MATLAB中设计好算法,并得到一组m文件。

其次在VC++下创建一个主控应用程序工程,MATCOM可以支持任意VC++工程类型的。那么在VC++主要完成界面和控制的工作。而主要算法仍然在MATLAB种开发,并通过MATCOM转换为C/C++模块以供VC++主控应用程序工程调用。

接着在VC++中点击VisualMATCOM工具条上的Addm-files to current project按钮。选中已经在MATLAB中已经设计好的一主m文件。这时可以看到在VC++的File View中增加了三个m-files,C++files created from m-files,Matrix文件夹。在三个文件夹分别对应这MATLAB的m源文件,m源文件生成的C/C++源文件,MATCOM的C/C++静态LIB库。虽然VC++工程编译及运行时都不需要这些MATLAB的m源文件,但是开发人员可以通过直接修改m源文件的方式来达到修改C/C++文件的目的。

加入工程中的主m文件生成的C/C++文件含有一个返回值为int型的main()函数,它封装好了m文件转换成的C/C++模块。可以仿照这个main()函数的形式在VC++的工程中其他C/C++源文件中要调用MATLAB开发程序的功能,代码形式如下:

initM(MATCOM_VERSION);

myfunction();

exitM();

在调用MATCOM生成的C/C++模块myfunciton()之前,需要调用initM(MATCOM_VERSION)函数来初始化Matrix类库v4500v。lib的调用,该函数可以在C/C++源代码的任意地方调用,调用结束要用exitM()函数来结束类库调用。此外由于initM()是通过一个静态变量而受保护的,所以它可以多次调用。头文件matlib。h中定义的常量MATCOM_VERSION保证了动态链接库与matlib。h版本相匹配。当然也可以在initM()函数和exitM()函数之间添加任意的符合MATCOM规范的代码。另外,可以通过使用全局变量实现参数在普通C/C++文件与通过MATCOM转换m文件生成的C/C++文件之间的传递。例如可在C/C++文件中定义全局变量,然后在通过MATCOM转换m文件生成的C/C++文件中声明使用。

四、调用MATLAB引擎

MATLABEngine库是Math Works公司提供的一组接口函数库,它提供了一种在用户程序进程中与独立的MATLAB进程通讯的方法,在Windows下使用ActiveX技术实现。MATLAB引擎采用C/S(客户机/服务器)模式,MATLAB作为后台服务器,而C程序作为前台客户机,通过Windows的动态控件与服务器通信,向MATLAB引擎传递命令和数据信息,从MATLAB引擎接收数据信息。用户可以在前台应用程序中调用这些接口函数,实现对MATLAB引擎的控制。它可以充分利用MATLAB的功能,包括调用工具箱函数和图形函数。

engOpen.engClose.engGetVariable.engPutVariable,engEvalString.engOutputBuffer等6个函数构成了Matlab引擎的基本库函数。下面通过一个简单的例子解释通过这些函数应用MATLAB引擎的一般步骤:

1.在需要调用MATLAB引擎的源文件头部加上对引擎库的包含#include“engine.h”。同时在工程里添加需要引用的库文件,通过菜单项Project选择Settings,在弹出来的ProjectSettings模式设置对话框中选择Link选项卡,在Object/librarymodules下面的编辑框中添加工程需要的库文件:libmatpm.lib,libmatlbmx.lib,libmatlb.lib,libmx.lib,sgl.lib,libmwsglm.lib,libmmfile.lib,libmat.lib,libeng.lib。

2.定义引擎指针,结构体变量和数组。

Engine*ep;//定义引擎指针

mxArray*T=NULL,*a=NULL,*d=NULL;

charbuffer[301];

double*Dreal,*Dimag;

doubletime[10]={0,1,2,3,4,5,6,7,8,9};

doubleAreal[6]={1,2,3,4,5,6};

3.启动MATLAB引擎

if(!(ep=engOpen(NULL))){

MessageBox((HWND)NULL,(LPSTR)"Can'tstartMATLABengine",

(LPSTR)"Engwindemo。c",MB_OK);

exit(-1);

}

4.构造矩阵进行赋值:

T=mxCreateDoubleMatrix(1,10,mxREAL);//创建一个1*10的矩阵变量T

memcpy((char*)mxGetPr(T),(char*)time,10*sizeof(double));//从time数组里面给矩阵变量T赋值

a=mxCreateDoubleMatrix(3,2mxREAL);//创建一个3*2的矩阵变量a

memcpy((char*)mxGetPr(a),(char*)Areal,6*sizeof(double));//从Areal数组里面给矩阵变量a赋值

5.通过MATLAB引擎库函数向MATLAB工作区间传送构造矩阵,同时调用MATLAB命令,完成相应的计算任务。

engPutVariable(ep,"T",T);//通过MATLAB引擎把矩阵变量T传入MATLAB工作区

engEvalString(ep,"D=。5。*(-9。8)。*T。^2;");//调用MATLAB命令,计算公式distance=(1/2)g。*t。^2的值

engEvalString(ep,"plot(T,D);");//绘制distance=(1/2)g。*t。^2的曲线

engEvalString(ep,"title('Positionvs。Timeforafallingobject');");

engEvalString(ep,"xlabel('Time(seconds)');");

engEvalString(ep,"ylabel('Position(meters)');");

engPutVariable(ep,"A",a);//通过MATLAB引擎把矩阵变量a传入MATLAB工作区

engEvalString(ep,"d=eig(A*A')");//计算特征值

engOutputBuffer(ep,buffer,300);//使用engOutputBuffer获取MATLAB的输出

engEvalString(ep,"whos");//把engEvalString(ep,"d=eig(A*A')");的输出返回到buffer里面

MessageBox((HWND)NULL,(LPSTR)buffer,(LPSTR)"MATLAB-whos",MB_OK);

d=engGetVariable(ep,"d");//获得特征值并且存入矩阵数组d中

if(d==NULL){

MessageBox((HWND)NULL,(LPSTR)"GetArrayFailed",(LPSTR)"Engwindemo。c",MB_OK);

}

else{

Dreal=mxGetPr(d);

Dimag=mxGetPi(d);

if(Dimag)

sprintf(buffer,"Eigenval2:%g+%gi",Dreal[1],Dimag[1]);

else

sprintf(buffer,"Eigenval2:%g",Dreal[1]);

MessageBox((HWND)NULL,(LPSTR)buffer,(LPSTR)"Engwindemo。c",MB_OK);

mxDestroyArray(d);

}

6.关闭引擎,释放内存。

engClose(ep);

mxDestroyArray(T);

mxDestroyArray(a);

五、三种方法比较

上述三种不同的VC++和MATLAB混合编程方案各有千秋,在具体应用中要结合需求进行选择。

利用mcc编译器,可以直接对MATLAB产生的m文件进行编译,可以有效提高代码的执行效率,在MATLAB提供的函数图形库的支持下,能将绘制各种复杂图形,而且可以脱离MATLAB运行环境,但待编译的m文件不能涉及MATLAB的内部类,出现编译文件嵌套时应改写m文件,生成的代码的可读性较差。

用MATCOM方式转换更加方便,生成的C/C++代码可读性好,支持图形函数,支持m文件编译过程中的文件嵌套情况,可脱离MATLAB环境,不过待编译的m文件不能涉及MATLAB的内部类。

MATLAB引擎不仅可以调用MATLAB中的C/C++函数,还可以调用工具箱中的函数,应用程序整体性能较好。同时,MATLAB Engine方式可利用MATLAB强大的图形功能,但该种方式的致命缺陷是需要MATLAB在后台运行,不能脱离MATLAB运行环境,不利于软件的开发。

六、结语

本文主要讨论了VC++与MATLAB的混合编程中在VC++中调用MATLAB的不同实现方案。采用这些方案使得科研工作人员避免耗费大量时间和精力在算法的实现编程及调试工作上。利用MATLAB的丰富的计算和图形处理功能完成软件核心算法设计,很大程度上降低了编程难度和工作量,缩短开发周期,提高软件可靠性。同时利用C/C++的高效快速完成图形界面设计,数据管理等工作,使得编程工作变得简单,这样科研工程人员可以把更多的时间和精力放在新算法的设计上,而不是放在算法的实现和程序编制中,对科研技术工作大有裨益。

参考文献

[1]飞思科技.MATLAB6 5应用接口编程[M].北京:电子工业出版社,2003.

[2]Math Works Inc.MATLAB user's Guide [s] 1998.

[3](Math Tools Corporation) Math Tools Function Reference Guide[s],1999.

[4](Math Tools Corporation)MID EVAMAT COM & Visual MATCOM Installation Guide.[s].1999.

上一篇:混合状态与时间序列数据的相关性问题 下一篇:浅谈《数字电路实验》的改革与实践