|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1 ~; N; U0 B/ m& w: x Z Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。" w% N6 _0 C0 U3 s) ?- \: e4 s
I9 [/ Z) P) w 本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。2 F( F; I' c- h- L5 T2 W
, `. x' h6 h6 a+ X
本文主要分以下几部分:
7 U3 D0 b! u& q" e+ p2 t9 n! R
( F$ }5 {% J% }8 X9 E Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。% T5 G; t" C0 y: p: A
& H) @0 j, V; Y0 E: S
Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。
, n0 v1 s' u% R9 p; A. T
x; a+ }, E8 E Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。) C2 A# F! F2 r: n8 a6 p. I
- L8 ^! D+ L7 w d 关于数据存储的说明。说明数据在Matlab中的存储方式。! ?/ O) z& j7 n9 V3 I
- K* q* v5 N" h* l# { W 注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。8 o) B8 Y9 G; A" a% m& U
, Y9 R( H4 M9 }1 H
# y1 u+ h% f. Whello Matlab
5 A; i( J: s- p$ A" h8 g! E7 U 我们一步步完成一个叫“Hello Matlab”的程序。0 t; e% e8 E a7 _( Y1 P
) T& b3 f, O, c9 Q 第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。
9 Y8 Q3 M0 W U) n8 H/ t8 S3 O6 q) Z3 X/ H, ~) u2 D
- #include "mex.h"
- void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
- mexPrintf("hello matlab in C/CPP.\n");
- }6 x' X( u: }1 y/ f3 R8 B( i# q5 v
& J' E7 ^9 P Z! A3 B9 c" ~
+ ]* R! V# b: i0 H2 `Code 1, abhimat.cpp u: s7 Y7 l3 F" T' k0 s9 |- P
“abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。0 q. F0 h* T. U1 p
: O2 p) P- }, p7 \5 C2 ^4 W
第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。
; N2 l. J4 h3 R3 s: C4 o. d2 s8 d2 A# x2 s
- mex -setup
7 V( {% O% |2 g) h
) m+ G; d( a5 {" s4 K7 w; s+ a
" m8 b* [4 n* {+ J" rCode 2, 设置Matlab的C/C++编译环境
: X! \( X# T4 H' A# h5 h) l I4 E8 q1 B: a% z1 Y8 i" `3 D4 @
完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。
9 P. R p# U$ x- D7 X
. j; @8 z6 ]3 M9 Q- d7 Z# h7 g# L, b& {7 B/ E, h# y7 L9 F
- mex abhimat.cpp
+ W% C$ v; n) n$ H+ g, b. n
# M+ d0 e, y! s( [' u' ^: B
) d* a7 M3 O: H) ^Code 3, 编译abhimat.cpp
( J/ r* p$ s0 k# g/ p+ m! L! e% T! J* R1 U, `3 P- p4 u* s
第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。6 m# B, h/ a! L& g) p9 N2 ^
2 \: {6 |! u6 i7 {1 T
细心的读者已经注意到了:
6 o4 T) p" R; Z! H0 f$ }2 ?, |% |* f# ]; F+ t& S* p! Q& Q
- 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
- Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。- V! o) s& c$ a+ q1 ^- o8 v
; J8 Y2 C- N4 e: K/ k
" s& v# \ L0 w5 n4 T5 rMatlab调用C/C++程序传递参数5 c# L! x" w9 m2 C
5 v, {# n/ b- ~( A; E/ ^6 o 此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。; R/ `# ]" }4 p( z
/ p% d& L) y& n. y- b& I1 ^ 给出Matlab中调用C/C++程序的一个实例,如code 4所示。
" m9 q* A" s9 ?6 b% ^ R7 A2 V% u) q" A. k
$ {3 x8 Q' S' y- c = [1 2;3 4;5 6];
- d = [1 1;1 1;1 1];
- [a, b] = abfunc(c, d);$ V' S0 s+ D2 E/ @7 {) O0 {$ o
7 ^, o* N V9 G/ Z* z6 D( _$ M' D4 ^% P3 i+ j4 f
Code 4, Matlab调用C/C++程序实例
6 W k/ l( H4 M' l
2 ~4 Y6 g4 B3 h 下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。/ a) v3 [' k! F! Q% j0 y: Z/ U; X9 }
( u: I% }( p4 V/ D5 a6 E! t
注意mexFunction函数中的四个参数,一一作出说明:( v/ u* y. |/ U
" [6 A' _! E- s" K nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。4 l B Q9 B; @% X3 m2 Y0 l" Z
' N3 ]9 Q* o2 C v6 Y; j9 F plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。2 K3 k. q$ i; ~1 o
+ t+ }4 C4 k- |" G( m# P nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。1 \' Y. X* C- w7 U. F! j
8 D8 o) s4 {$ d* G4 L5 M _
prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。/ W! T: c4 M* R6 A! D: S8 M k
1 f9 K$ s. n9 [; A) h mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。& k l+ N1 `8 T3 e" P
4 t9 R U5 t# R, F* Y4 H
下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。# Z' `9 I, C3 T0 c1 J4 n w7 U
# ~5 U! a F5 {0 b+ Z- #include "mex.h"
- void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
- double *p_c, *p_d;
- double *p_a, *p_b;
- int c_rows, c_cols;
- int d_rows, d_cols;
- int numEl;
- int n;
- mxAssert(nlhs==2 && nrhs==2, "Error: number of variables");
- c_rows = mxGetM(prhs[0]);// get rows of c
- c_cols = mxGetN(prhs[0]);// get cols of c
- d_rows = mxGetM(prhs[1]);// get rows of d
- d_cols = mxGetN(prhs[1]);// get cols of d
- mxAssert(c_rows==d_rows && c_cols==d_cols, "Error: cols and rows");
- // create output buffer
- plhs[0] = mxCreateDoubleMatrix(c_rows, c_cols, mxREAL);
- plhs[1] = mxCreateDoubleMatrix(c_rows, c_cols, mxREAL);
- // get buffer pointers
- p_a = (double*)mxGetData(plhs[0]);
- p_b = (double*)mxGetData(plhs[1]);
- p_c = (double*)mxGetData(prhs[0]);
- p_d = (double*)mxGetData(prhs[1]);
- // compute a = c + d; b = c - d;
- numEl = c_rows*c_cols;
- for (n = 0; n < numEl; n++)
- {
- p_a[n] = p_c[n] + p_d[n];
- p_b[n] = p_c[n] - p_d[n];
- }
- }3 J" g3 p$ V* w: M/ A8 E' W
( z$ |% q" u- i* t6 ~
Code 5, abfunc.cpp的实现
/ Z* s+ ~% T" f, i' a7 c% A$ e ?8 `% t% [
说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。% }5 j3 u- b. ^" l, U
P: s+ j$ I5 S! d! i5 O: g 编译并测试Code 5中的代码,参见Code 6。
, n1 \8 O5 v: W3 P, q U; R! M6 W8 \( V2 X. s
- mex abfunc.cpp
- c = [1 2;3 4;5 6];
- d = [1 1;1 1;1 1];
- [a, b] = abfunc(c, d);
@# A5 y+ L' U8 P' j$ |$ O
/ p8 B' g1 Q% b, b. S6 a" \# |- F1 a
Code 6, Code5的测试代码! c5 j0 F$ T1 R2 E4 {
9 s8 B0 p4 P* V0 r$ ~( q+ B Code 6的输出结果如下:
6 s) k8 P$ t/ h" u* Y$ f
. b8 L N) n+ o$ g8 X# b3 u4 n- a =
- 2 3
- 4 5
- 6 7
- b =
- 0 1
- 2 3
- 4 5- L! W2 J+ y) F
% `$ S+ ?: t X) T' E$ s% w4 ]6 d
: k0 ^7 Y, I& J
关于数据存储的说明) B2 H5 K% O' ~" B0 [
3 Q2 M" |. I7 D) U
Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。
+ a$ U( Z; q% U+ ~7 U E0 l
6 Y5 Z0 F! x' O+ p3 Y7 h
2 T2 ?7 O* q2 [: [" z0 Z; O! ]" qMatlab与C/C++混合编程的方法论
- C; \, {2 M! T, g+ o9 q( m$ C( [
, X4 e. o% C J& V, o( H鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:
# n( y& V9 m- y' M% D. `0 L( ^4 q" o
4 Y9 M ]$ ^4 `+ P" F9 p( D* i
9 d$ ~$ V$ ~; P6 H2 g- g, o7 n: P; Y图 1、Matlab与C/C++混编方法论流程图
' n7 H' e# y. E# K: Y: i y, C5 Q |
|