Matlab 作为当今世界上应用最为广泛的数学软件, 具有非常强大的数值计算、数据分析处理、系统分析、图形显示甚至符号运算的功能。已经在如生物工程,图像处理,语音处理,雷达探空,声纳探水,地震探地,以及控制论,系统论等各个领域得到广泛的应用。它是一个完整的数学平台,在这个平台上,用户只需寥寥数语就可以完成十分复杂的功能,大大提高了工程分析计算、图像处理的效率。但是Matlab 强大的功能只能在它所提供的平台上才能使用,即用户必须在安装Matlab 系统的机器上才能执行*.m 文件。这样当用户需要将在Matlab 下已开发完毕的复杂算法应用到高级语言开发环境下时就带来了问题,是将现成的东西集成高级语言开发的程序中呢?还是用高级语言再重新实现一遍?显然大家所期望的是减少工作量, 最好能将Matlab下开发好的程序或函数直接应用到高级语言开发的程序中,这就是Matlab与高级语言的混合编程问题。
VC++是当前Windows 下的主要编程语言之一,它能方便地形成应用软件中所需要的各种用户界面和工具并直接与系统及底层硬件交换数据。用VC++开发的系统具有容易维护升级、界面友好、代码效率高、执行速度快等一系列优点,因此已成为目前应用软件开发中广泛采用的主要工具之一。因此,如何将Matlab与VC++进行有效的混合编程广受工程科研人员的关注。解决这个问题,不仅能更好地发挥Matlab 强大的功能,还能快速地进行软件开发,尤其是当软件开发中需要实现复杂的数学算法、图形处理时尤为迫切。研究VC++与Matlab的混合编程具有很大的实际意义。
MATLAB 与Visual C++结合的方法有多种,但其实用程度与范围不同。目前主要有以下三种方式。
1. 通过Matlab引擎(Engine)
采用客户机/服务器(Client/Service)的计算模式,通过windows的ActiveX通道和MATLAB进行结合。MATLAB引擎采用客户机和服务器计算方式,提供了一组Matlab API函数,用户不必关心Matlab引擎是如何实现的,只要调用这些函数即可。正是通过这些API函数实现应用程序进程之间的传递函数,从而实现Matlab与VC的混合编程。具体应用中,往往在VC中设计程序框架, VC的C语言或C++语言的程序作为前端客户机,它向Matlab引擎传递命令和数据信息,通过调用MATLAB引擎在后台与MATLAB服务器建立连接,实现动态通信。这种处理方法不要求链接整个Matlab,只需嵌入必要的Matlab引擎库,节省了大量的系统资源,使应用程序整体性能更好,处理效率更高,但这种混合编程的方法需要MATLAB在后台适时运行不能脱离Matlab环境,否则影响了程序的通用性,因此这种方法在实际开发过程中很少采用。
2. 通过DLL实现混合编程
DLL是动态链接库的英文缩写,是一个可执行的二进制文件。把很多通用的功能放在DLL 中,可供多个应用程序调用,而不是每个应用程序在连接时都要增加一个库中目标代码的拷贝。通过Matlab自带的Compiler编译器,可以把由Matlab编写的m 函数文件编译成动态链接库(dl1)。或者通过Matlab提供的组件功能,运用VC+十向导自动生成m文件的动态链接库。在VC程序中调用封装的函数,实现数值算法的运用。这种方法只需在开发和发布中包含其生成的动态库就可以了,可以使程序脱离Matlab可以整体减少文件外部存储空间的占有量,并实现了代码共享。
3.使用COM技术实现混合编程
COM技术是一种应用广泛、方便灵活的方法,是利用MATLAB提供的Deploy Tool工具实现MATLAB与C/C++的混合编程。COM给软件开发人员提供了一种共享二进制代码的方法,这种共享并不局限于某种编程语言。
VC与Matlab混合编程(在VC中调用DLL)的实现
本人所用系统为windows7旗舰版,MATLAB为R2008a和Microsoft Visual C++6.0编程环境。
一、 MATLAB编译环境的设置
为了能够使用MATLAB的Complier将*.m函数文件编译为动态链接库DLL,必须对MATLAB的环境做出相应的设置。具体做法如下:
在MATLAB的Command Window下输入命令 mbuild –setup,并根据MATLAB的提示选择合适的编译器,笔者使用的是Microsoft Visual C++6.0,进行对C++连接环境的设置。过程如下:
>> mbuild -setup
Please choose your compiler for building standalone MATLAB applications:
Would you like mbuild to locate installed compilers [y]/n? y
Select a compiler:
[1] Lcc-win32 C 2.4.1 in D:/PROGRA~1/MATLAB/R2008a/sys/lcc
[2] Microsoft Visual C++ 2005 in d:/Program Files/Microsoft Visual Studio 8
[3] Microsoft Visual C++ 6.0 in D:/Program Files/Microsoft Visual Studio
[0] None
Compiler: 3
Please verify your choices:
Compiler: Microsoft Visual C++ 6.0
Location: D:/Program Files/Microsoft Visual Studio
Are these correct [y]/n? y
Trying to update options file:
C:/Documents and Settings/hk/Application Data/MathWorks/MATLAB/R2008a
/compopts.bat
From template: D:/PROGRA~1/MATLAB/R2008a/bin/win32/mbuildopts/msvc60compp.bat
Done . . .
在MATLAB的Command Window下输入命令 mex –setup,进行对编译环境的设置。过程如下:
>> mex -setup
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n? y
Select a compiler:
[1] Lcc-win32 C 2.4.1 in D:/PROGRA~1/MATLAB/R2008a/sys/lcc/bin
[2] Microsoft Visual C++ 2005 in d:/Program Files/Microsoft Visual Studio 8
[3] Microsoft Visual C++ 6.0 in D:/Program Files/Microsoft Visual Studio
[0] None
Compiler: 3
Please verify your choices:
Compiler: Microsoft Visual C++ 6.0
Location: D:/Program Files/Microsoft Visual Studio
Are these correct [y]/n? y
Trying to update options file: C:/Documents and Settings/hk/Application Data/MathWorks/MATLAB/R2008a/mexopts.bat
From template: D:/PROGRA~1/MATLAB/R2008a/bin/win32/mexopts/msvc60opts.bat
Done . . .
*********************************************************************
Warning: The MATLAB C and Fortran API has changed to support MATLAB
variables with more than 2^32-1 elements. In the near future
you will be required to update your code to utilize the new
API. You can find more information about this at:
http://www.mathworks.com/support/solutions/data/1-5C27B9.html?solution=1-5C27B9 Building with the -largeArrayDims option enables the new API.
*********************************************************************
二、创建动态链接DLL
这里我们用的方法就是使用MATLAB的mcc命令将*.m文件编译为动态链接库(*.dll)。
关于mcc有很多参数可以使用,而且有多种用法,具体的可以参见MATLAB的帮助。
其中MATLAB提供了三种使用MATLAB编译器的方式:
(1) 在MATLAB环境中使用mcc命令;
(2) 在系统命令环境中使用mcc.exe(在Windows上);
(3) 在MATLAB环境中使用Deployment Tool.
前两种方式所需要的命令行参数是一样的。
假设要把file1.m和file2.m编译成可执行文件:
mcc –m file1 file2
假设要把file1.m和file2.m编译成C语言动态链接库文件:
mcc –w lib:mylib –T link:lib file1.m file2.m
假设要把file1.m和file2.m编译成C++语言动态链接库文件:
mcc –w cpplib:mycpplib –T link file1.m file2.m
三、使用MATLAB编译器和VC6.0实现混合编程(通过例子说明)
1、MATLAB中的操作
(1)创建mccdemol.m文件,内容如下:
(2) 在MATLAB命令行下,将mccdemol.m编译成C++动态链接库文件。可以执行如下命令:(带图形的和不带图形的有区别,这里主要是带图形的编译)
>> mcc -W cpplib:libmccdemol -T link:lib mccdemol.m
命令执行完成后,将在工作目录产生使用MATLAB编译生成库文件所需的相关文件。
2、建立VC对话框工程
创建一个基于MFC对话框的工程,工程名称为MccDemol,如下图所示:
设计对话框界面如图:
在文件MccDemolDlg.cpp : implementation file中包含头文件,如下所示:
#include "libmccdemol.h"
修改对话框的初始函数如下:
BOOL CMccDemolDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
bool res = false;
res = mclInitializeApplication(NULL,0);
if (!res)
{
MessageBox("初始化Application错误!");
}
res = libmccdemolInitialize();
if (!res)
{
MessageBox("初始化Lib错误!");
}
return TRUE; // return TRUE unless you set the focus to a control
}
为对话框添加WM_DESTROY消息,使用快捷键“Ctrl+W”,调出MFC Class Wizard对画框,如下图所示:
添加如下消息响应函数:
void CMccDemolDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
bool res;
res = mclTerminateApplication();
if (!res)
{
MessageBox("结束程序错误!");
}
libmccdemolTerminate();
}
为确定按钮添加消息响应函数
void CMccDemolDlg::OnButtonRun()
{
// TODO: Add your control notification handler code here
mccdemol();
mclWaitForFiguresToDie(NULL);
}
本例中用到了MATLAB图形功能,所示使函数“mclWaitForFiguresToDie(NULL)”,在没有用到MATLAB的图形功能的库文件时,不需要此函数。
3、VC中的设置
将在MATLAB环境下编译后的生成文件“libmccdemol.h”、“libmccdemol.dll”、“libmccdemol.lib”和“libmccdemol.ctf”(这个文件在有的编译器下生成后瞬间消失,如本例中,所以建议如果生成有的话,就将其添加,如没有就不用了。CTF文件见后面注释)复制到当前工程目录。
为工程添加库文件“libmccdemol.lib”和“mclmcrrt.lib”,如下图所示。
编译运行工程,可以看到运行结果,单击确定按钮,弹出Figure窗口。这与MATLAB环境下直接运行的结果相同。