◆ 上海大学通信与信息工程学院 杨高波
Matlab是一个具有强大的矩阵运算、数据处理和图形显示功能的软件,其输出结果可视化,编程效率极高,极少的代码即可实现复杂的运行,然而其边解释边执行,运算效率较低,实现相同功能的代码跟其他编程平台相比运行时间相对较长,且不适合作为通用的编程平台。因此,许多Matlab的应用程序需要使用诸如VC之类的通用编程平台,实现Matlab与VC的混合编程,这样有助于发挥Matlab和VC的各自优势。
集成的几种实现方法
为了实现混合编程,Matlab 5.0以后版本自带了C语言编译器(Compiler), 可以将M文件转换为C-MEX或C/C++程序。根据Matlab是否运行,一般将Matlab与VC混合编程分为两大类:Matlab在后台运行和可以脱离Matlab环境运行。
1.Matlab引擎(Engine)采用客户机/服务器(Client/Server)的计算方式,通过Windows的ActivcX通道和Matlab接口。在具体的应用中,VC的程序作为前端客户机,通过调用Matlab Engine在后台与Matlab服务器建立连接,实现动态通信。这种方法实现较为简单,不要求连接整个Matlab,只需要嵌入必要的Matlab Engine库,可大大地节省系统资源,但这种Matlab在后台运行,运行效率低下。
2.Mideva是Mathtools公司推出的一种Matlab集成编译开发平台,提供对Matlab程序文件(M文件)的解释执行和开发环境支持。经过简单设置后Mideva可以将M源文件转换为C/C++,然后添加到MSVC、C++ Builder的工程中。
3. 另一种方法是先利用Mideva直接生成EXE文件(方法是启动Mideva,在菜单“File->Compile to exe”中, 选出需要转换的M文件),然后在VC中通过Shell调用,常见的外部函数有shellexec()或winexec()。这种方法简单方便,但运行时出现一个控制台窗口,而且由于VC和Matlab之间不能交互,通用性差,仅适用于VC中调用Matlab实现图形显示的场合。
4. 最新也是最方便的方法是通过Matlab 6.0 Add-in实现Matlab与VC的混合编程。
以上方法1需要Matlab在后台运行,方法2、3、4可以脱离Matlab环境运行。
Matlab Add-in
Matlab 6.0以后版本对其Compiler作了较大的改进,其支持更多的数据类型,更强的优化功能,更为重要的是其Matlab Add-in提供了一个Matlab和VC直接集成的途径。它具有一些新的特征:快速集成M文件到C++工程中,创建独立的 C/C++应用程序或C MEX DLL;通过M文件创建共享库或MEX文件;内含Visual Matrix Viewer,调试过程中可以查看矩阵变量的值; 直接修改M源文件而不是修改生成的C/C++文件;方便快捷地打包应用程序等。
Matlab Add-in的安装:
1. 启动Matlab,运行“mex-setup”,按照菜单提示选取MSVC。它将配置MEX使用MSVC为默认的编译器(创建C-MEX文件必需),并安装Matlab Add-in所需文件到MSVC目录。
2. 在Matlab环境下运行“mbuild-setup”, 按提示选取MSVC。它将配置使用MSVC为默认的编译器(创建独立应用程序必需),并安装Matlab Add-in所需的Matlab Compiler和C/C++数学库文件到MSVC目录。
3. 在Matlab环境下运行“cd(prefdir)”和“mccsavepath”。它将保存当前Matlab路径到mccpath文件中,这是因为Matlab Add-in脱离Matlab运行,否则它无从知道Matlab路径。
4. 在MSVC环境中配置Matlab Add-in,方法是:从菜单“Tools -> Customize”选择“Add-ins and Macro Files”选项卡,选中“Matlab Add-in”, 点击“Close”。MSVC工具栏出现Matlab Add-in图标,以后每次启动VC,自动加载Matlab Add-in。
5. 配置Windows系统。在Windows 95/98系统下,找到config.sys, 添加一行:shell= c:\ command.com /e:32768 /p(Windows ME有所不同,需设置Conagent.exe的属性Memory选项卡的Initial Environment值为4096)。从表面看,VC的环境设置也是步骤较多,但只需设置一次。
程序示例
下面以创建一个Standalone程序为例具体说明。启动MSVC,打开“File->New”菜单,选择Project,选择“Matlab Project Wizard”, Project Name命名为Mytest, 点击Next,你可以选择所生成的应用程序的类型:Windows Console EXE、C-MEX DLL、M-MEX DLL、Shared M-DLL; C程序还是C++程序;选取Debug、Release模式;选择是否生成Main函数;是否需要支持图形。这里选择生成C++程序,其余采取默认设置,点击“Finish”,出现对话框要求选择添加到工程中的M源文件,选择文件testplot.m后,这时你可以看到MSVC调用MCC生成一个混合M文件和C的工程。在“File View”选项卡中可以看到添加的M文件和自动生成的C++文件。
这时大功告成,即可按F7编译后按F5运行了,运行结果如下图所示。
程序运行结果
这里用到的testplot.m内容如下(先在Matlab里编辑好):
function mytest()
t=0: 0.05*pi: 2*pi;
y=sin(t);
plot(t,y,‘b*’);
可以通过双击Matlab M-files文件夹下testplot.m打开观察。生成的testplot.cpp代码如下(略有删节):
// MATLAB Compiler: 2.1 Date: Sat Nov 03 16:37:08 2001
#include “testplot.hpp”
#include “libmatlbm.hpp”
static double _array0_[41] = { 0.0,.157,....};
//自动生成的数组
void InitializeModule_testplot() {
}
void TerminateModule_testplot() {
}
static void Mtestplot();
_mexLocalFunctionTable _local_function_
table_testplot = { 0, (mexFunctionTableEntry *)NULL };
void mlxTestplot(int nlhs, mxArray * plhs[], int nrhs, mxArray * prhs[]) {
MW_BEGIN_MLX();
{
if (nlhs > 0) {
error(mwArray(“Run-time Error: File: testplot Line: 1 Column: 1 The function \‘testplot\’was called with more than the declared number of outputs (0). ”));
}
if (nrhs > 0) {
error(mwArray(“Run-time Error: File: testplot Line: 1 Column: 1 The function \‘testplot\’ was called with more than the declared number of inputs (0).”));
}
Mtestplot();
}
MW_END_MLX();
}
#line 1 “D:\\ygbtest\\testplot.m”
static void Mtestplot() {
#line 1 “D:\\ygbtest\\testplot.m”
mclMlineEnterFunction(“D:\\ygbtest\\testplot
.m”, “testplot”)
#line 1 “D:\\ygbtest\\testplot.m”
mwLocalFunctionTable save_local_
function_table_(&_local_function_table_testplot);
#line 1 “D:\\ygbtest\\testplot.m”
mwArray ans(mclGetUninitializedArray());
#line 1 “D:\\ygbtest\\testplot.m”
mwArray y(mclGetUninitializedArray());
#line 1 “D:\\ygbtest\\testplot.m”
mwArray t(mclGetUninitializedArray());
// t=0: 0.05*pi: 2*pi;
//
#line 2 “D:\\ygbtest\\testplot.m”
mclMline(2);
#line 2 “D:\\ygbtest\\testplot.m”
t = mwArray(1, 41, _array0_, (double *)NULL);
//
// y=sin(t);
//
#line 3 “D:\\ygbtest\\testplot.m”
mclMline(3);
#line 3 “D:\\ygbtest\\testplot.m”
y = sin(mwVv(t,“t”));
//
// plot(t,y,‘b*’);
//
#line 4 “D:\\ygbtest\\testplot.m”
mclMline(4);
#line 4 “D:\\ygbtest\\testplot.m”
ans.EqAns(Nplot(0, mwVarargin(mwVv(t, “t”), mwVv(y, “y”), “b*”)));
#line 4 “D:\\ygbtest\\testplot.m”
mclMlineExitFunction();
#line 4 “D:\\ygbtest\\testplot.m”
}
自动生成的testplot_mainhg.cpp代码如下:
#include “matlab.hpp”
//加入Matlab头文件
#include “libsglinit.hpp”
#include “testplot.hpp”
//加入应用程序头文件
static mexFunctionTableEntry function_table[1] = { { “testplot”, mlxTestplot, 0, 0, &_local_function_table_testplot } };
static _mexcppInitTermTableEntry init_term_table[1] = { { InitializeModule_testplot, TerminateModule_testplot } };
static _mexcpp_information _main_info = { 1, 1, function_table, 0, NULL, 0, NULL, 1, init_term_table };
可以看到没有添加一句C/C++代码,即生成了一个Matlab的Standalone应用程序(是不是太容易啦)。需要注意两点: 一是添加到MSVC工程的文件应当为一个函数文件,而不能是一个Script文件,否则会出现错误提示; 二是最好不要修改生成的C/C++代码,如果需要改动,可以通过在MSVC工作区中直接修改M文件(无须在Matlab环境中),重新编译即可。你可以通过在M文件中设置断点,在运行中通过Matrix Viewer观察Matlab变量的值。
目前通过Add-in实现Matlab与VC的混合编程也有一定的不足:如目前并不支持所有的Matlab的函数;生成的程序代码有些繁杂等。估计Matlab 6.0以后的版本在这方面肯定有所改进的。
结 论
Matlab Add-in提供了一种实现Matlab和VC混合编程的直接集成的途径,通过它可以很方便地生成Matlab和VC的混合程序。在图像处理等需要大量计算的工程应用场合有广泛的应用价值。
|