学 士 学 位 论 文
BACHELOR ’S THESIS plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL); n=mxGetM(plhs[0]); y=mxGetPr(plhs[0]); hilb(y,n); }
该程序是一个C语言程序,它也实现了建立Hilbert矩阵的功能。MATLAB命令窗口输入以下命令:mex Matlab_1.cpp,即可编译成功。进入该文件夹,会发现多了两个文件:Matlab_1.asv和Matlab_1.dll,其中Matlab_1.dll即是MEX文件。运行下面程序:
tic
a=Matlab_1(1000); toc
elapsed_time = 0.0470
由上面看出,同样功能的MEX文件比m文件快得多。
3.3 MATLAB计算引擎
MATLAB引擎函数库是MATLAB提供的一系列程序的集合,它允许用户在自己的应用程序中对MATLAB函数进行调用,将MATLAB作为一个计算引擎使用,让其在后台运行,这样可以简化前台用户程序的设计任务。[5]
当用户使用MATLAB引擎时,相当于在后台启动了一个MATLAB进程。MATLAB引擎函数库在用户程序与MATLAB进程之间起一个桥梁的作用,完成两者的数据交换和命令的传送。
在实际应用中,MATLAB作为Activex的自动化服务器,接受通过引擎传来的数据和指令信息并进行相应的处理,然后将结果经过引擎返回给发送请求的客户机。但这种方式需要MATLAB在后台适时的运行,如果用户没有安装MATLAB,应用程序就无法正常运行,而且应用程序与MATLAB间通过字符流传数据和命令参数,整个算法在MATLAB中执行,从而降低了程序的执行效
11
学 士 学 位 论 文
BACHELOR ’S THESIS 率,故而其实际应用不多。[1][6]
简单举例:
如以下C 代码段可以完成完整的数据交互功能:
Engine * ep; ep = engOpen( 0) ; / / 定义并打开引擎
mxArray * M, * N; / / 定义mxArray 指针用于交互数据 double C[ 500] , D[ 500] ; , , / / C 数组赋初值
M = mxCreateDoubleMatrix ( 1, 500, mxREAL) ; / / 创建 Double 型实阵列
memcpy( ( char * ) mxGetPr (M) , ( char * ) C, 500* sizeof ( double) ) ; / / 将数组C赋至阵列的实部
mxSetName ( M, / MM0) ; / / 设置阵列M 在Matlab Workspace 中对应的变量名
engPutArray( ep, M) ; / / 将阵列M 的内容交互到Matlab Workspace 中的相应变量MM
engEvalString( ep, / s= awgn(MM, 8) ;0 ) ; / / 调用Matlab 函数
N = engGetArray( ep, / s0 ) ; / / 将Matlab Workspace 中的变量s 交互到阵列N 中
memcpy( ( char * ) D, ( char * )mxGetPr (N) , 500* sizeof ( double) ) ; / / 将阵列N 实部赋至数组D
mxDestroyArray(M) ; mxDestroyArray(N) ; / / 释放阵列空间 engClose( ep) ; / / 关闭引擎
这种方法通过引擎函数实现了在C 语言中调用MATLAB函数, 包括ToolBox 函数和作图函数等, 但是不能脱离MATLAB环境而生成独立运行的程序, 所以只适于算法仿真或C程序算法调试过程中使用, 而不适于开发。在C 中调用MATLAB 的ToolBox 函数, 可以大大提高仿真编程效率, 减少重复开发。engEvalString 函数中调用的MATLAB 函数在引擎中仍然是以解释性执行的, 其执行效率并不能提高, 所以调用运算量较大的函数时计算时间仍然很长。
12
学 士 学 位 论 文
BACHELOR ’S THESIS 3.4 MATLAB编译器
MATLAB编译器是一个运行于MATLAB环境的独立工具。MATLAB编译器的主要功能是把M程序转换成C代码,然后在调用外部C编译器把产生的源代码编译、链接成用户指定的格式。MATLAB编译器产生的可执行文件或者组件在运行时只需要一个简化的组成形式运行环境,而并不需要MATLAB本身。这个组件形式的MATLAB运行环境可以很方便地从MATLAB派生并且免费发布。这使MATLAB得应用不再只是局限于程序的原型设计和开发。利用MATLAB编译器,完全能够在MATLAB环境中快速开发,可以直接交付用户使用的应用程序,从而极大的缩短应用程序的开发周期。[7]
简单举例:
首先建立两个.m 函数文件: function a = addmatrix(a1,a2) a = a1 + a2;
figure;imshow(mat2gray(a)); title('加法结果显示'); eturn
保存为addmatrix.m。
function m = multiplymatrix(a1, a2) m = a1 * a2;
figure;imshow(mat2gray(m)); title('乘法结果显示'); return
保存为multiplymatrix.m。
这两个.m函数主要执行加法和乘法运算,并将计算结果以图形方式显示。
3.5
前面介绍的方法都不能脱离MATLAB环境独立运用, 而只是C语言程序与MATLAB系统交互的方法。应用MATLAB提供的MCC 命令和C语言数学函数库,
13
学 士 学 位 论 文
BACHELOR ’S THESIS 可以将MATLAB 中的M 代码源文件翻译成C 语言代码文件, 从而实现在C 程序中调用MATLAB中丰富的数据处理和分析库函数。应用MCC 命令的前提是在MATLAB系统中已经用命令mex - setup 和mbuild - set2up 对编译器进行了配置。C语言数学函数库包含了MATLAB 的Matrix 数学计算核心, 是以mxArray 结构体 为核心构建的。通过MCC 命令可以将M 文件转换为基于C 语言数学函数库的C语言源代码文件。需要注意的是, MCC 命令只能转换MATLAB 函数文件,而不能转换脚本文件, 所以脚本类型的M 文件应该先改写为函数类型的M 文件。将转换后的C 语言源文件加入C 工程中, 最终可以编译成脱离MATLAB 环境独立运行的可执行文件。[8]由MCC 转换的C 源文件代码冗余度较大, 在将其加入C 工程时可以将源文件全部加入, 也可以只将其中有用的代码拷贝到自己的程序中。因为这些代码还是以mxArray结构体或mwArray 类为基础的, 所以在编译调试过程中需要有libmmfile . lib、libmatlb. lib、libmx. lib、libmat. lib 静态库文件的支持。由MCC 命令转换后的C 代码冗余度大、可读性不强, 而且速度上仍然比正常编写的C程序慢, 不过由此换来的高开发效率和可靠性往往是值得的。[10][13]
简单举例:
test. m 实现的是两个矩阵的加和减: function[ a, b] = test( x, y) a= x+ y; b= x- y;
利用mcc-t-L Cpp test. m 命令生成test. hpp 和test. cpp 文件。头文件test. hpp 的内容如下
/ /
/ / MATLAB Compiler: 2. 2 / / Date: Tue Jan 15 08: 17: 19 2002 / / Arguments: “- B”“macro default”“- O” “all”“- O”“fold scalar mxarrays: on” / / “- O”“fold non scalar mxarrays: on” “- O”“optimize integer for loops: on”“- O” / / “array indexing: on ”“- O”“optimize
14
学 士 学 位 论 文
BACHELOR ’S THESIS conditionals: on”“- t”“- L”“Cpp”“test. m” / /
# ifndef test hpp # define test hpp 1 # include “libmatlb. hpp”
extern void InitializeModule test( ) ; extern void TerminateModule test( ) ; extern mexLocalFunctionTable local function table test;
extern mwArray test(mwArray * b, mwArray x = mwArray: : DIN, mwArray y = mwArray: : DIN) ; # ifdef cplusplus extern“C” # endif
void mlxTest( int nlhs, mxArray * plhs[ ] , int nrhs, mxArray * prhs[ ] ) ; # endif
在VC 中调用test 函数的主程序文件如下: # include < iostream. h> # include “test. hpp” void main( ) {
double data[ ] = {1, 3, 2, 4};
mwArray a( 2, 2, data) , b( 2, 2, data) , c, d; c= test(&d, a, b) ;
cout< < a< < end1< < b< < end1; cout< < c< < end1< < d< < end1;
cout< < inv( a) < < det( b) < < end1; }
15