数学建模社区-数学中国

标题: C++Builder调用Matlab [打印本页]

作者: 韩冰    时间: 2005-1-26 12:50
标题: C++Builder调用Matlab
<>  </P>1 {4 v! f. Z$ G$ E5 o
<>  Borland C++Builder是一种新颖的可视化编程语言。在工程应用中,我们一般 </P>
" A9 n0 c, [) w8 n( X3 j<>用C++Builder语言编写应用程序,实现交互界面、数据采集和端口操作等,但 </P>' E$ n8 J9 h; X$ {4 K
<>C++Builder在数值处理分析和算法工具等方面,其效率远远低于Matlab语言。在 </P>% g' F* g% {5 J8 {
<>准确方便地绘制数据图形方面,Matlab语言更具有无可比拟的优势。此外, </P>
) ~2 n4 \2 s3 x& ]. ?7 k<>Matlab还提供功能强大的工具箱。但Matlab的缺点是不能实现端口操作和实时控 </P>
3 A2 k4 D) t+ ^; c+ @$ y<>制。因此,若能将两者结合运用,实现优势互补,将获得极大的效益。 </P>
9 b$ t" @1 |. B<>本文结合实际介绍了应用Borland C++Builder3.0开发的Windos应用程序中,对 </P>
+ V4 O3 ]$ n# k2 w; ]3 F/ G<>Matlab的调用方法。 </P>
5 A9 g- W% C1 V3 X/ I, K<>一、C++Builder调用Matlab的实现方案 </P>
6 a0 v1 A* m" w* y; S+ F3 T<>1. 实现思路 </P>, A, v0 D" T/ J% F+ H2 Z' V; _% L
<>在高版本的Matlab中(如Matlab V4.2)提供了DDE接口,用户可以通过Windows的 </P>5 @  h- `( [0 B" [0 f4 B
<>DDE通信基制实现外部调用。这种实现方式比较简单,但将增大主程序代码,影响 </P>% r9 v! N2 j, Y
<>运行速度。 </P>
9 L! N$ B: F8 t& w5 x2 |$ f9 i<>在Windows系统中,DLL是一种很特别的可执行文件,可以被多个Windows应用程序 </P>! U8 Y/ `4 Z( [2 h) W7 s+ E
<>同时访问,具有固定的共享数据段。该数据段的数据在DLL被Windows下载前会一 </P>7 A8 E4 n7 D; k
<>直保留在内存中,因此可以通过DLL实现用户程序与Matlab之间的数据传输和函数 </P>1 i9 I7 J! N1 G" e# c
<>调用。 </P>
9 O% e8 D! \5 S+ Q<>具体地说,就是利用Matlab的32位动态连接库(DLL),生成相应的可以被 </P># S4 z+ u1 f' s9 Y# L: l1 D
<>C++Builder调用的DLL,用来提供二者之间的基本支撑环境。只需在用户程序中加 </P>
$ p0 Z' h1 n: |" }: t% \5 s<>载该DLL,即可实现其数据段的共享。然后在用户程序中操作DLL数据段的数据,并 </P>
! b4 R+ E, u' |5 t% j<>通过某种方式在用户程序中使Matlab执行该DLL,就可实现用户程序对Matlab的调 </P>
; A# V' ]9 h8 @& h8 b/ j<>用。其形式可以是混合编程或函数调用,非常方便而高效。 </P>
$ d, j5 k( O" ?: ]0 a: l) [<>2. 实现方式 </P>
- o9 c* Y$ o, u1 G4 I+ z; a<>Matlab提供了可外部连接的DLL文件,通过将其转换为相应的Lib文件,并加以必要 </P>% O- d; j* p( N8 ~9 Q
<>的设置,就可以在C++Builder中直接进行Matlab函数调用,实现C++ Builder语言 </P>) l1 V& S8 d+ B! l3 K
<>与Matlab语言的混合编程。 </P>6 b8 U8 I" ?% Q) W! a4 z
<>(1) 运行环境要求 </P>% ?; r! M1 h7 B. H& Y; G
<>由于Matlab提供的是32位的DLL。其运行环境要求是Matlab V4.2或更高版本。 </P>0 N% d% u, \! f4 _
<>C++Builder可以进行32位编程,这里我们采用的是V3.0版本。 </P>, H4 N! C1 ^: J$ x1 N; L& K
<P>(2) C++Builder下LIB文件的生成 </P>- Z2 N6 Q0 ?9 ^" U; ~, G
<P>Matlab提供的Def文件允许用户通过Implib命令生成相应的Lib文件。其命令格式 </P>
5 y/ U& K- K4 }$ n& h% a<P>为 </P>
6 P5 l+ |: e4 g, m<P>Implib ???.lib ???.def </P>. T3 _5 M& b7 Q. b2 W6 G' C
<P>在&lt;matlab&gt;\extern\include目录下,提供了如下三个.Def文件: </P>
: k. P- ~. F) c0 M4 G$ Y<P>_libeng.def,_libmat.def,_libmx.def </P>
. R9 B) A/ h( W! k0 S<P>通过上述命令可以生成相应的三个Lib文件。这些Lib文碱中包含了可外部调用的 </P>
3 i+ S$ q: k. L3 k0 u2 ]! R<P>Matlab函数的必要信息。 </P>1 l# N. `4 O4 f: _1 \
<P>二、实现计算和绘图 </P>  {+ D* m, n$ ]
<P>为清楚起见,通过一个简单的CBuilder例程进行说明。该实例通过调用Matlab实 </P>/ N2 u& F& Q2 F! O, R
<P>现矩阵运算并绘制图形,来演示C++Builder对Matlab的调用。 </P>
( {7 v/ f7 `. _. C<P>在C++Builder编辑环境中,建立一个新的窗体MyForm,并放置一个按钮Demo。将工 </P>- X, t8 v) L& R* S8 V  Q8 Y# \
<P>程文件命名为Try.prj,其主函数为try.cpp。在主函数中,我们将使用一个实现 </P>
- E' r; ^( F0 d1 i7 f% q' e7 ^<P>Matlab调用的子函数DemoMatlab,作为按钮Demo的响应事件。其源代码如下: </P>
/ t* s6 f5 z* N9 J+ H6 N. |1 ?  n<P>#include &lt;vcl.h&gt; </P>& w4 C! E. p# i
<P>#pragma hdrstop </P>
5 g  X5 U5 h  @<P>#include "Unit1.h" </P>
' E* ~0 C/ Y0 o; z* Q- @' M8 ?<P>#pragma package(smart_init) </P>
! c% p5 r1 H- I; K- Y  l+ Z; B8 E<P>#pragma resource "*.dfm" </P>! A* ]0 v0 Z+ J6 l8 U: _, W
<P>TMyForm *MyForm; </P>
2 W. l2 h9 L5 w4 _, ?* j2 w6 ?<P>__fastcall TMyForm::TMyForm(TComponent* Owner) </P>4 d# B- R7 T) `: f1 u
<P>: TForm(Owner) </P>
% D# y$ V: T( k. L, j% P5 A<P>{ </P>( v) b) y# l; R( p( T* G+ c
<P>} </P>
  }3 T* r1 y) K; t: p) g4 j<P>void __fastcall TMyForm:emoClick(TObject *Sender) </P>! i( p  I( E" V/ m: n1 q
<P>{ </P>" l# @0 E0 P( X& J8 k3 u% n0 b/ ^
<P>DemoMatlab(); //演示Matlab语言调用 </P>8 {4 k) p  l3 b1 X1 s
<P>} </P>
0 Y9 u" i' b; e  R, A0 x<P>为了调用Matlab中的函数,必须进行必要的设置,将包含这些函数的文件加入工程 </P>
8 v) h7 \5 K' @# J- S$ l<P>文件Try.prj。以下是操作过程: </P>
% c# p/ y" X8 _  f& Z2 `<P>1. 在头文件中加入Engine.h。其包含了启动Matlab调用和关闭的函数声明。 </P>! m- f1 f" O- W7 [) B
<P>2. 打开Project|Option...对话框,点击Directories/Conditionals。 </P>
( f3 C+ ?% W3 y! U$ V* h<P>● 在Include Path中,加入目录路径&lt;matlab&gt;\extern\include,该路径包含了 </P>
0 w8 L3 f! W" v3 l) a<P>engine.h和matlab.h等有用的头文件。 </P>" Z& V- n9 D9 y3 l
<P>● 在Library Path中,加入&lt;matlab&gt;\bin和&lt;matlab&gt;\extern\include。这两个 </P>+ Z& `# p2 a' \& D+ h- |
<P>目录路径包含了可外部调用的DLL和LIB文件。 </P>: V9 {& R* t" P: d/ _' Q2 ^
<P>3. 点选Project|Add to Project...对话框,加入如下库文件: </P>  w1 D" @. l* e! t" r  L
<P>_libeng.lib,_libmat.lib和_libmx.lib。 </P>
$ \0 N* w( Y& `5 Q4 T* c6 C, k<P>在进行了这些必要的设置之后,我们就可以选用适当的函数来实现目标。 以下是 </P>
7 p8 x% u3 T* I" c! `6 t* K! @) D<P>子函数DemoMatlab的程序代码。 </P>2 q0 w2 V( [' p8 M
<P>void DemoMatlab </P># T, k, l2 [( l$ r0 p
<P>{ </P>, N) B3 b* ~* p$ X
<P>Engine *eng; </P>  H+ p$ Q6 g4 p: T  R
<P>//定义Matlab引擎 </P>5 `/ Q/ J$ s, _+ U3 b
<P>char buffer[200]; //定义数据缓冲区 </P>
; |; W' f& i0 G<P>int array[6]={1,2,3,4,5,6}; </P>/ G& ~. U8 l4 [+ P" D
<P>mxArray *S = NULL, *T = NULL; </P>
& @& o' q0 ]0 C% T<P>engOpen(NULL); //打开MATLAB 引擎 ---1 </P>
- t: x7 J) Z% z( A) O<P>S= mxCreateDoubleMatrix(1,6, mxREAL); </P>2 I6 y1 r- }% Q& j. h$ A) s
<P>// 产生矩阵变量 </P>$ E7 u- R, i& L
<P>mxSetName(S, "S"); </P>& H$ c8 j) R: G9 W/ N
<P>memcpy((char*) mxGetPr(S),(char *) array, 6*sizeof(int)); </P>3 y1 y. K& j' T
<P>engPutArray(eng, S); //将变量X置入Matlab的工作空间 </P>" Z0 i2 n, z( _6 q5 j. E# k+ N1 b
+ O7 x; C: ]; }: q
<P>engEvalString(eng, "T = S/S.^2;"); //计算 </P>! w# w) j+ d$ h1 G7 M' R
<P>engEvalString(eng, "plot(S, T);"); //绘制图形 </P>& ]* `4 T! c; Q8 P; v
<P>…… …… </P>
7 O! t% L+ o) a$ \/ O2 H<P>engOutputBuffer(eng, buffer, 200); //获取Matlab输出 </P>
9 E/ o" @3 J. h4 y" D! v1 X! e8 K# z<P>T = engGetArray(eng, "T"); //获得计算结果----2 </P>
1 B/ y1 ?1 v) [3 [( p$ O: \5 g4 o5 W<P>engClose(eng); //关闭Matlab引擎,结束调用 </P>
) Q% t' ^  Q" T, X$ s9 j<P>mxDestroyArray(S); //释放变量 </P>+ |3 ^* o" r. V) m8 |' z; n
<P>mxDestroyArray(T); </P>4 ]) S* f* w+ E6 s/ V
<P>} </P>, h- U4 x, K, ^4 |4 J
<P>若还需要执行其他功能和任务,那么按照上面介绍的方法,进行变量声明后,在1、 </P>
' Z6 G2 O2 K. Q8 J0 r<P>2处加写需要的语句即可。 </P>: o+ M- Y( N2 O8 @
<P>当然,使用这种方法调用Matlab不能脱离Matlab环境的支撑。但当我们不需要看 </P>
8 f2 i) ~7 P# j5 A/ ]0 O% F<P>到Matlab的命令窗口时,可将其赋予Swhide属性而加以隐藏。 </P>2 v6 `* P8 q8 m3 ?4 e
<P>  </P>! K. a1 Y" w7 I) u0 j* r9 Y
<P>国防科技大学机电工程与仪器系 张云洲 </P>




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5