您好,欢迎来到投聚财经。
搜索
您的当前位置:首页matlab编译器和api

matlab编译器和api

来源:投聚财经




12 MATLAB编译器和API

几乎所有使用过MATLAB的科技人员,无不为该软件的简洁、便捷和功能之强大和可靠所震撼,同时也对MATLAB产生了新的期望:一,希望程序能运行得更快;二,希望获得可摆脱MATLAB环境而运行的可执行软件;三,希望从其他“非MATLAB的外部程序中调用MATLAB

本章前6节介绍MATLAB版编译器(Compiler)。由于1.2版与2.0版差异较大,又由于2.0版缺少1.2版具有的优化功能,因此内容安排上将兼顾地论及两个版本。值得指出的是:除Mathworks外,还有其他一些公司生产的编译器,其中比较著名的是MathTools公司的Mediva;据该公司自称,性能优于Mathworks的,且具有绘图功能。

本章第7节论及API应用程序接口,扼要地介绍不同平台间的数据传送和MATLAB引擎技术。节后算例演示了,如何从外部调用MATLAB引擎。

12.1编译器2.0概述

12.1.1编译器2.0的功能

12.1.3编译器2.0 的局限性12.1.2编译器2.0的性能改进

[circle.m]
clf;r=2;t=0:pi/100:2*pi;x=r*exp(i*t);

plot(x,'r*');axis('square')

2)对这脚本文件直接编译将因错误而失败
mcc-x circle
???Error: File "circle" is a Script M-file and cannot becompiled with the current Compiler.

Errorin ==> H:\MATLAB53\toolbox\compiler\mcc.dll

3)把脚本文件改写成函数文件。

[circle_f.m]:
functioncircle_f(r)

clf;t=0:pi/100:2*pi;x=r*exp(i*t);

plot(x,'r*');axis('square')

4)再对circle_f.m 进行编译,将顺利通过。



mcc -x circle_f

%mcc 是编译指令,详见12.4 节。







5)运行生成的MEX文件circle_f.dll

circle_f(0.5) %调用circle_f绘制一半径为0.5的圆

whichcircle_f %查询所调用的circle_f的路径全称。

d:\mywork\circle_f.dll

?5

?4

?3

?2

?1

?

??

??

??

??

??

??

?

?5

12.1.4-1 MEX文件circle_f.dll所画的圆

12.2编译器的安装和配置

12.2.1配置MATLAB 编译器的前提准备


12.2.1-1 SelectMATLAB Componets】对话窗的选项局部图

12.2.2为产生MEX文件进行预配置





12.2.2.1 MATLAB编译器应用程序mex的设置

12.2.2.1-1 为产生MEX文件所产生的配置屏1




12.2.2.1-2 为产生MEX 文件所产生的配置屏2 12.2.2.2 配置正确性的验证

1mex 应用程序的验证




cdd:\mywork %把用户目录指定为当前目录

mexmy_yprime.c %my_yprime.c文件生成my_yprime.dll文件

my_yprime(1,1:4)%运行my_yprime.dll文件

whichmy_yprime %获得my_yprime.dll文件的位置信息

ans=

2.0000 8.9685 4.0000 -1.0947

d:\mywork\my_yprime.dll

2)在MATLAB命令窗中验证mcc应用程序

mcc -x my_yprime_m
my_yprime_m(1,1:4)
which my_yprime_m
ans =
2.0000
8.9685
4.0000
-1.0947
d:\mywork\my_yprime_m.dll

%<1>

3)在DOS提示符后验证mexmcc应用程序

12.2.2.2-1 DOS状态下验证编译指令

12.2.3.1


12.2.3.1-1 为产生外部应用程序所产生的配置屏1



12.2.3.2 MATLAB 编译器mbuild应用程序的设置(1.2 版) 12.2.3.1-2 为产生外部应用程序所产生的配置屏2

12.2.3.3

cd d:\mywork %把用户目录指定为当前目录

mbuildmy_ex1.c %d:\mywork下生成my_ex1.exe文件

12.2.3.2-1 DOS窗口运行验证程序my_ex1.exe所得的结果

2mcc应用程序的验证

mcc-p my_hello.m %<1>





12.2.3.2-2 DOS窗口运行验证程序my_hello.exe所得的结果

3)在DOS状态下验证mbuildmcc工作正确性

12.2.3.2-3 DOS状态验证编译指令

12.3.1M 文件创建CMEX 文件的入门算例

【例12.3.1-1】先编写M文件,然后生成相应的MEX文件。该文件用以判断方阵是否奇异。

cdd:\mywork

1)在MATLAB的编辑器中,编写下面的函数文件exm1.m

[exm1.m]
function y=exm1(A)
[m,n]=size(A);
if m~=n;
error('An input matrix should be n-by-n.')
end
r=rank(A);
if r==m
disp('This matrix isnonsigular')
else
disp('This matrix is sigular')
end
2)把该函数文件存放于用户目录d:\mywork下。
3)在MATLAB命令窗中,运行以下指令对exm1.m进行编译。



mcc-x exm1 %编译m文件。

4)调用MEX文件exm1.dll进行计算
A=[1,0,1;2,1,0;4,1,4]
exm1(A) %调用exm1来判断矩阵A是否奇异。whichexm1 %查询所调用的exm1的路径和全称。

A=
1 0 1
2 1 0
4 1 4
Thismatrix is nonsigular
d:\mywork\exm1.dll

12.3.2M文件创建外部应用程序的入门算例

【例12.3.2-1】建立一个脱离MATLAB环境,可运行的外部程序。该程序的功能是:对于给定矩阵A,如果存在S使得S-1AS=Λ,则要求出一个S,否则给出信息说明所给的矩阵A不能对角化。

1)编写两个M函数文件:exm2.mexm2_f.m。(第一个文件是主文件。)[exm2.m]
functionexm2
A=[4,0,0;0,3,1;0,1,3];
S=exm2_f(A)

function S=exm2_f(A) [m,n]=size(A); if m~=n[exm2_f.m]

e=eig(A);

same=0; end;

fori=1:m-1
forj=(i+1):m
ife(j)==e(i)
same=1;
end
end
end
%A可以对角化的条件是A具有互异特征值或者A为埃尔米特矩阵。

ifany(any((A'-A)))&(same==1)
error('矩阵无法对角化!');
end
[v,d]=eig(A);
S=v;

2)把这两个函数文件存放于用户自己的目录d:\mywork,并在MATLAB中运行检验。

exm2
S =
1.0000 0 0 0 0.7071 0.7071 0 0.7071 -0.7071





3)生成的外部可执行程序。在MATLAB指令窗中,运行如下指令mcc-m exm2 exm2_f

4)打开DOS窗口,在d:\mywork目录下,运行exm2.exe,得如图12.3.2-1的结果。

12.3.2-1 DOS窗口运行生成程序exm2.exe所得的结果

12.4编译指令mcc简介

12.4.1mcc的基本调用格式

12.4.2 mcc 的选项标志

12.4.2.2

【例12.4.2.2-1】假设当前目录上存在一个文件exm3.m,现要求利用M编译器将它转换为C++
12.4.2.1

语言的源码文件,并要求将原M文件中那注释区的内容作为所得C++源码文件的注释。

mcc -t -L Cpp -A annotation:comments exm3 12.4.2.3 设置缺省选项

%得到exm3.cppexm3.hpp

【例12.4.2.3-1】假设已在d:\mywork 下创建了文本文件mccstartup (请注意:该文件不可带

扩展名),该文件的内容包括若干编译指令的选项。现要求利用该文件,从exm3.m 出发得

C++语言的源文件。

cd d:\mywork
type mccstartup
-t -L C -A annotation:none

!copy mccstartup h:\y9857\temp !copy exm3.m h:\y9857\temp

%d:\mywork设为当前工作目录%打印文本文件mccstartup的内容

%mccstartup转移到临时目录下%将待编译M源码转移到临时目录下

!del mccstartup , %删除mccstartup

!del exm3* %删除原有的编译后文件

dir mccstartup

dir h:\matlab53\bin\mccstartup

dir exm3*
1 file(s) copied 1 file(s) copied mccstartup not found.

%当前目录下是否含有mccstartup%<matlab>\bin 下是否含该文件
%当前目录下是否含有exm3*




h:\matlab53\bin\mccstartupnot found.
exm3*not found.

!copyh:\y9857\temp\exm3.m d:\mywork
mcc -L Cpp exm3 %<1> 1 file(s) copied
???Error: The options specified will not generate any output files.Please use one of the following options to generate an executableoutput file:
-x (generates a MEX-file executable using C)
-m (generates a stand-alone executable using C)
-p (generates a stand-alone executable using C++)
-S (generates a Simulink MEX S-function using C)
Ortype mcc -? for more usage information.

Errorin ==> H:\MATLAB53\toolbox\compiler\mcc.dll

!copy h:\y9857\temp\mccstartup d:\mywork mcc -L Cpp exm3
dir exm3*
!del mccstartup
1 file(s) copied
exm3.cpp exm3.hpp exm3.m

12.4.2.4 编译器1.2 选项简介

%mccstartup拷贝到当前目录%<2>
%<3>

【例12.4.2.4-1】要求利用1.2 版编辑器对文件exm4.m 进行操作,目标是获得C MEX 文件

1)在5.3 MATLAB 指令窗中的执行指令mcc -V1.2 exm4C 语言的可执行文件。

mcc -V1.2 -em exm4

mcc exm4 mcc -em exm4

12.5编译文件的性能优化

12.5.1优化原M 文件的性能

12.5.1.1 提高向量化程度

【例12.5.1.1-1】本例演示:M 文件与MEX 文件、向量运算与循环运算的速度比较。1)编写如下两类函数M 文件。

function y=sa(x)
x=x+(x==0)*eps;
y=sin(x)./x;

function y=saf(x)
n=length(x);
for k=1:n

end

x(k)=x(k)+(x(k)==0)*eps;


y(k)=sin(x(k))/x(k);





2)在MATLAB指令窗中,对sa_mex.msaf_mex.m进行编译。

cd d:\mywork
mcc -x sa_mex
mcc -x saf_mex

%<1>
%<2>

3)运行四个文件,记录运算时间

t=-2*pi:pi/500:2*pi;

tic;sa(t);tt(1)=toc;

tic;saf(t);tt(2)=toc;

tic;sa_mex(t);tt(3)=toc;

tic;y=saf_mex(t);tt(4)=toc;

4)结果显示和比较

plot(t,y,'r-');grid

?

?8

?6

?4

?2

?

??

disp('运算速度比较') ??

??

运算速度比较 disp(tt)

12.5.1.2 对数组进行预置

【例12.5.1.2-1】以上节例12.5.1.1-1为基础。saf.m文件中数组变量xy的大小随循环进

行而增长,这大大减慢了运算速度。本例演示:在循环前对进行变量预置的好处。

1)编写如下文件,以saf_pro.msaf_pro_mex.m为名,将之保存在当前目录下。

functiony=saf(x)

n=length(x);

x=zeros(1,n);y=zeros(1,n);

fork=1:n

x(k)=x(k)+(x(k)==0)*eps;

y(k)=sin(x(k))/x(k);

end

2)产生编译文件
mcc -x saf_mex
mcc -x saf_pro_mex



3)运行
t=-2*pi:pi/500:2*pi;







tic;saf(t);tt(1)=toc;

tic;saf_pro(t);tt(2)=toc;

tic;saf_mex(t);tt(3)=toc;

tic;y=saf_pro_mex(t);tt(4)=toc;

4)速度比较

disp('运算速度比较')

disp(' saf.m saf_pro.m saf_mex.dll saf_pro_mex.dll')

disp(tt)

运算速度比较

saf.m saf_pro.m saf_mex.dll saf_pro_mex.dll

2.8600 0.6600 2.6300 0.4400

12.5.1.3 避免调用复数域函数

12.5.2利用mcc(-V1.2)的优化性能

12.5.2.1 编译时指定优化选项-r-i

【例12.5.2.1-1】求如下非线性差分方程组在10000个点上的值。观察原M文件、无选项和

有选项MEX文件运行速度的不同。

?

?
xk?1?1?yk?1. 4 xk 2

x0?0, y0?0

?yk?1?0. 3 xk

x=zeros(1,n);y=zeros(1,n);

for k=1:n-11)利用MATLAB编辑窗口编写如下M 函数文件

function[x,y]=m_henon(n)

end

cdd:\mywork

mcc-x mex20_henon %2.0编译器产生普通MEX文件<1>

mcc-V1.2 -ri ri_mex12_henon %1.2编辑器产生优化的MEX文件<2>

3)计算各文件运行时间费用的相对值。

n=10000;

t=zeros(3,2);

for k=1:2
tic;m_henon(n);t(1,k)=toc;
tic;mex20_henon(n);t(2,k)=toc; tic;ri_mex12_henon(n);t(3,k)=toc; end
t=t/t(1,1);

4)显示比较结果
filename=[ ' m_henon';
' mex20_henon'; 'ri_mex12_henon';];

%运行两次,以做比较

disp([' 各文件运行开销的相对值比较表'])


disp(blanks(1)')

%产生一个空行

disp([' 文件名第一次运行第二次运行']) disp([filename blanks(3)' blanks(3)' num2str(t)])

%blanks 产生两个空列






各文件运行开销的相对值比较表

文件名第一次运行第二次运行

m_henon 1 0.78086
mex20_henon 0.69753 0.59259
ri_mex12_henon 0.015432 0

12.5.2.2 利用变量类型申明优化性能

12.5.2.3 利用编译注记优化性能

【例12.5.2.3-1】编译注记%#ivdep的应用举例。

1)编写如下两个函数M文件,并存放在d:\mywork目录上。

[ivdep0.m]

functionA=ivdep0()

A=1:10;

A(5:9)=A(3:7);

[ivdep.m]

functionA=ivdep()

A=1:10;

A(5:9)=A(3:7);

2)分别对这两个文件进行编译。%#ivdep

cd d:\mywork

tic;A0=ivdep0;t0=toc;
tic;A=ivdep;t=toc/t0;

4)显示结果

A0,A

disp(['使用编译注记%#ivdep后的运用时间仅为原来的 'num2str(t)]) A0=
1 2 3 4 3 4 5 6 7 10 A =
1 2 3 4 3 4 3 4 3 10

使用编译注记%#ivdep后的运用时间仅为原来的 0.15152

12.6创建的外部应用程序

12.6.1外部程序的工作特点和创建过程




12.6.1.1 外部程序与MEX文件的不同工作特点

12.6.1.2 外部程序创建过程说明

12.6.2关于指令mbuild

12.6.3借助编译指令mcc创建应用程序

12.6.3.1 创建应用程序时mcc的使用格式和常用选项标志

12.6.3.2 由全M源文件产生EXE应用程序

【例12.6.3.2-1】创建一个适应“超定”、“恰定”、“欠定”线性方程求解的示例性应用程序。

1)编写以下两个M函数文件

[LLS.m]
functionLLS()
Ae=5;%<2>%<3> Av=2;
[A,b]=LLSDATA(Ae,Av);
x=A\b;
%以下都是为获得较清晰的显示而编写

if Ae>Av S='超定';S='恰定';

end

cs=blanks(Ae)'; elseif Ae<Av

ns=fix(Ae/2); %从零方向最接近空白列长之半的数
As=cs;As(ns)='A';
bs=cs;bs(ns)='b';
es=cs;es(ns)='=';
disp([Ascs es cs num2str(A) cs cs cs cs cs bs cs es cs num2str(b)])disp('方程的解')
nxs=fix(Av/2);
cxs=blanks(Av)';
xs=cxs;xs(nxs)='x';
exs=cxs;exs(nxs)='=';
disp([xscxs exs cxs num2str(x)])

[LLSDATA.m]
function[A,b]=LLSDATA(Ae,Av)
n=max(Ae,Av);
WA=magic(n);

A=WA(:,1:Av);
if n>Ae
A=WA(1:Ae,:);
end





b=ones(Ae,1);
2)对存放在d:\mywork上的这两个文件进行编译

12.6.3.2-1 应用程序LLS.exe解超定方程示例

3)把LLS.m文件第23行改为Ae=3;Av=5,重新编译、运行,结果见图12.6.3.2-2



12.6.3.2-2 应用程序LLS.exe解欠定方程示例

12.6.3.3 由含feval指令的M文件生成EXE文件
【例12.6.3.3-1】采用编译指定法生成一个可以计算方阵各种特征量的外部应用程序。1)编写函数M文件:mat_feat.mmy_det.m

[mat_feat.m]

function mat_feat(f_name)

%给定的被分析矩阵

%<1>

disp('被分析矩阵')

%<2>

A=magic(4)

N=8;

%为字符串比较而设的字符串长度 8



n=size(f_name,2);
ff_name=[f_name blanks(N-n)];

%测量输入字符串的长度%给输入字符串补充空字符,使长度为8

if ff_name==['my_det' blanks(2)] disp('矩阵 A 的行列式值 = ')







elseifff_name==['rank'blanks(4)]
disp('矩阵A的秩=')
elseifff_name==['norm'blanks(4)]
disp('矩阵A2-范数=')
elseifff_name==['cond'blanks(4)]
disp('矩阵A的条件数=')
elseifff_name==['eig'blanks(5)]
disp('矩阵A的特征值=')
elseifff_name==['svd'blanks(5)]
disp('矩阵A的奇异值=')
else
disp('您输入的指令,或者不是本函数文件所能解决的,或是错误的!')end
d=feval(f_name,A);
disp(d)

[my_det.m]
functiond=my_det(A)
d=det(A);

2)创建计算给定矩阵秩的EXE文件
mcc-V1.2 -pm mat_feat f_name=rank

!mat_feat WARNING: Reference to uninitialized variable被分析矩阵(3)所生成的mat_feat.exe可脱离MATLAB 而运行。

矩阵 A 的秩=

4)求矩阵行列式值的EXE文件创建指令、验证运行指令、及运行结果。mcc-V1.2–p –m mat_feat f_name=my_det
!mat_feat
被分析矩阵
[ 16 2 3 13 ;
5 11 10 8 ;
9 7 6 12 ;
4 14 15 1 ]

矩阵A的行列式值=
0

【例12.6.3.3-2】采用编译注记法生成一个可以计算方阵行列式值的外部应用程序。1)假定想创建一个计算矩阵行列式值的应用程序,那么只要在上例mat_feat.m文件的第<1><2>行之间插入以下两行指令,而M文件的其余部分都不必改动。

%#function my_det
f_name='my_det';



2)用以下指令对M 文件进行编译,便可得到正确的EXE 文件。



mcc–p mat_feat

【例12.6.3.3-3】当feval调用的是MATLAB C++库中的函数时,可以采用更简单的feval

入宗量直接赋值法,实现EXE文件的创建。如创建一个计算方阵特征值的外部应用程

序。

1)只要在例12.6.3.3-1mat_feat.m文件第<1><2>行中间插入如下一条指令即可。

f_name='eig';

2)用以下指令对M文件进行编译,便可得到正确的EXE文件。mcc–p mat_feat

3)以下是运行指令和结果
!mat_feat

被分析矩阵

A=
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1

矩阵 A 的特征值 =
34.0000

8.9443
-8.9443
-0.0000


12.6.3.4
x

1)为了让读者了解函数

y ?

1

sin(

xe

0 . 6

x

)

,对将生成的EXE 文件的运行结果正确性做直


x







观的判断。先运行以下指令绘制如图12.6.3.4-1所示的函数曲线。xx=0:0.01:5;

yy=SAA(xx); %SAA.m文件见本例第2
plot(xx,yy)
x0=2;
x=fmins('SAA',x0);
y=SAA(x);
plot(xx,yy,'b-',x,y,'r.','MarkerSize',20),grid





??

??

?

?и

??

??

??

?

??

??

??

0

1

y ?

1

2

xe

3

)

4

5

12.6.3.4-1函数

sin(

0 . 6

x

2 附近的局部最小值


x






2)编制以下M函数文件,并存放在用户自己的工作目录上。

[fcpp.m]

functionfcpp(fun)

%#functionSAA %被泛函调用函数的编译注记是必须的。

fun='SAA'; %对泛函指令中第一输入宗量具体化也是必须的。

xs=1;

x=fmins(fun,xs);

disp(blanks(2)')

disp('外部程序 fcpp.exe运行结果显示')y=feval(fun,x);

disp(blanks(2)')

disp(ss);

disp(['

[SAA.m]

functiony=SAA(x)

x=x+(x==0)*eps;

y=sin(x.*exp(0.6*x))./x;

3)在MATLAB指令窗或DOS环境中运行以下编译指令,在用户目录上产生

fcpp.exe

mcc–p fcpp

4)在DOS中运行fcpp.exe的操作情况和结果如图12.6.3.4-2





12.6.3.4-2生成的程序fcpp.exeDOS中的运行结果

12.6.3.5 C/C++源码和M源码文件混合生成EXE应用文件

【例12.6.3.5-1】主程序为C源码文件,被调用程序为M文件。

1)主文件fileinc.c和被调用的mrank.m文件如下

[fileinc.c]
#include<stdio.h>
#include"matlab.h"
#include"templib.h"

int main(int argc, char **argv[]) { int n ;
*mxGetPr(N)=n;
r = mlfMrank(N);
mlfPrintMatrix(r);
mxDestroyArray(r);
mxDestroyArray(N);
TemplibTerminate();
return 0;
}

[mrank.m]

functionr=mrank(n)

r=zeros(n,1);

fork=1:n

r(k)=rank(magic(k));

end

2)编译混合源码文件
mcc–t –W lib:Templib -T link:exe mrank fileinc.c

mcc –t –W lib:Templib -T link:exe fileinc.c mrank
3)在DOS中分别运行mrank.exefileinc.exe 的结果如图12.6.3.5-1




12.6.3.5-1 混合源码产生的mrank.exefileinc.exe运行结果

12.7API应用程序接口

12.7.2数据的输入输出12.7.1MEX 文件

12.7.2.2 12.7.2.1

12.7.2.3 不同平台间数据传递

12.7.3MATLAB引擎

【例17.7.3-1 】在C 源程序中调用MATLAB 引擎来计算三次多项式

x

3

?x

?

5

的根。

1)编写源程序engexam.c
#include<windows.h>
#include<stdlib.h>
#include<stdio.h>
#include"engine.h"

intPASCAL WinMain (HANDLE hInstance,
HANDLE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)

{

Engine *ep;


mxArray *P=NULL,*r=NULL;



char buffer[301];
double poly[4]={1,0,-2,5}; /*三次多项式的系数*/




/*启动本机MATLAB引擎,如果出错则退出程序。

如想启动远程主机上的MATLAB,则用相应主机名代替\0*/if (!(ep=engOpen("\0"))) {
fprintf(stderr,"\nCan'tstart MATLAB engine\n"); returnEXIT_FAILURE;}

/*创建变量P,将poly变量中定义的多项式系数值拷贝至该变量P*/
P=mxCreateDoubleMatrix(1,4,mxREAL);
/*给变量P取名为p,将P传递到引擎空间,p将被运用于MATLAB表达式中*/mxSetName(P,"p");
memcpy((char*)mxGetPr(P),(char *)poly,4*sizeof(double));
engPutArray(ep,P);

/*利用MATLAB求解多项式根,并写至缓冲区*/
engOutputBuffer(ep,buffer,300);
engEvalString(ep,"r=roots(p)");

/*将缓冲区中的内容输出屏幕窗口,关闭MATLAB引擎,释放指针P*/MessageBox(NULL,buffer,"Engexam.c--多项式x^3-2x+5的根",MB_OK);engClose(ep);
mxDestroyArray(P);

}

return EXIT_SUCCESS;



12.7.3-1 运行程序engexam.exe得到的信息窗口



Copyright © 2019- tjwe.cn 版权所有

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务