|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
, |- m5 K& E9 w Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。4 [, C- Z1 G4 Y3 O5 S) o9 f
# m ]& B# _# ], O 本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。' h! d( G( T+ S% m& A: D
" L$ K9 D* [" h5 ?" G4 z% L 本文主要分以下几部分:
& \$ D3 F' v) ]; v
, h) V' X/ ]0 {4 u Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。- q* ~, x! g7 ?! J1 g7 }! e
6 f5 T E7 T Z+ U- D4 H4 }2 @) L Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。5 @; l0 [. M V
* C; U/ e& O6 X" n) @, l Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。
2 Q& N. x( \, F2 e" y Y2 u2 ?% _6 n
关于数据存储的说明。说明数据在Matlab中的存储方式。
4 m/ _0 M* i7 Z$ Q; u7 p: H' {. t5 T3 M* d
注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。
Y! r: b2 X' m2 X4 {4 u! w0 ? W( A) X
J. ]$ j6 M5 |
hello Matlab+ A) K* W- h" F) B/ |6 z
我们一步步完成一个叫“Hello Matlab”的程序。# r/ A C5 `0 ^
. g& {& a! A3 d0 M1 n: v
第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。
% M7 y R [ N% N5 u3 S+ e
2 X0 r- D% X- \$ ]- #include "mex.h"
- void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
- mexPrintf("hello matlab in C/CPP.\n");
- }) z! h5 Y1 M8 O/ W
) z. f4 p8 L3 |4 e& Q
8 {5 b- i, Z9 l! X8 s0 x' e; CCode 1, abhimat.cpp& V4 L6 v0 Y% B c B
“abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。
6 J1 s$ R9 e# b- r9 z; c( Q5 v5 c" V1 t
第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。
" R) V1 O3 a1 a {% \6 F+ b" X, ?4 G! U0 e+ B) H" N
- mex -setup
( J$ E+ z6 X4 y1 ~. F9 E5 E2 O; ]# g1 R ; |6 x/ N. E3 D4 ]/ M1 r3 W& C! O
, L( y9 B" I; G" z
Code 2, 设置Matlab的C/C++编译环境. C; Z4 l1 V" f( e4 }
- O" w* y, w: q" K$ q+ R6 }9 T1 d
完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。
# q+ A) M& n- x; {8 W3 J1 l9 q
1 J6 B; M( v! d; ]
2 T1 m/ |2 _6 h4 Z9 {- mex abhimat.cpp$ K4 x' q/ Q d4 Y1 c3 _5 S$ U6 P
, }* |' I1 X+ I" z9 V# Q8 W: L
; Q* R( Z7 V4 ?* p7 _2 U$ C) S+ c
Code 3, 编译abhimat.cpp- j' L2 @5 a3 z/ }/ o3 G
, b8 Z: L& O! n4 A, ~3 \" D
第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。- w0 y% c' n! e3 n7 ]
9 x- Q; p$ O. f/ g6 d9 r! } 细心的读者已经注意到了:9 J0 R+ S; M9 t' s) n t# V
$ c4 | p4 [0 W& }
- 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
- Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。
, a+ }( H3 Y5 h z3 h2 D& D3 \! r 0 ~3 g5 S/ X7 e* i, x, ~
2 L/ d2 ^/ J0 \) M6 CMatlab调用C/C++程序传递参数
; H+ L* ]6 ^# z' w) R6 k# ]1 ?0 t+ x1 W3 z9 S Q
此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。
4 c4 h8 o7 f) {, z: B4 S/ U. R+ b6 N( O4 v" t4 b
给出Matlab中调用C/C++程序的一个实例,如code 4所示。 _% Y; U6 h" n, b
* V1 F4 e5 {8 O
4 w H) x8 `5 C- c = [1 2;3 4;5 6];
- d = [1 1;1 1;1 1];
- [a, b] = abfunc(c, d);& w5 y' K! _3 m1 v- \# p
9 N0 I7 a- W6 H1 j
2 ^, b4 k) u4 x2 v" sCode 4, Matlab调用C/C++程序实例
, S9 N [* y0 j" A) d) P; r$ y' w6 a( |: P! h
下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。3 p: T7 o: c: b
" B7 J$ B }+ i4 N7 I& w$ p7 k
注意mexFunction函数中的四个参数,一一作出说明:
0 Z6 n7 u* C: L/ ?- x8 u
! D/ q) T, x4 G1 [2 Q R9 e+ q nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。
0 m/ r( i1 Z6 ?5 x3 Y0 j; @' Y4 u8 X8 X( d' R0 B
plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。! |2 ]& `; R* l8 D
: o6 Y7 d) x& C( t
nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。
) k- F* }5 Q1 O6 I
+ f5 K" |. _( \4 a' p prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。
% T, C% F7 k+ F( L3 k9 ^1 W+ Q8 {0 j: I1 C/ {5 P6 `/ _ ~
mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。5 O. r4 s( J! Q( j+ @
! K( H5 R- J$ p; w6 x
下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。2 a% }: L7 r/ `6 }' \. ]% L, I* X
2 _5 Z+ y. e0 \% ], f9 D
- #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];
- }
- }
! C( w) i8 y. H+ g4 `! Z+ P
$ B8 t3 \/ A8 @ W; DCode 5, abfunc.cpp的实现 y5 B- l3 k& I8 D, t! K5 r
/ Y: w+ Z' u/ ^! t V
说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。
: k" g' {/ ~; ]- Q$ G3 B$ ^1 e
% R6 a) `2 q! ]2 g1 d$ t) Q3 L 编译并测试Code 5中的代码,参见Code 6。
8 s* q7 P) j7 g- N c
8 z- a7 n8 p9 s% G `" ]- mex abfunc.cpp
- c = [1 2;3 4;5 6];
- d = [1 1;1 1;1 1];
- [a, b] = abfunc(c, d);
% I8 a( U0 c0 v6 V5 B- x ! [4 ?2 ]" W5 I9 F3 b* t
% t5 g) N C' [$ j, `
Code 6, Code5的测试代码: E& w0 z: a( v
+ d* Z1 [3 Z' U& y& e
Code 6的输出结果如下:
* }9 t% a; C% Y) A9 i7 Y* }3 h2 \
- a =
- 2 3
- 4 5
- 6 7
- b =
- 0 1
- 2 3
- 4 5) J7 a0 ^8 h C- c% y
. D9 E4 o( V* J2 B: `: k
, A( t% U6 A2 U" G; u* x& k: e7 M
关于数据存储的说明
) m9 F0 Y* n6 D9 G* q, F n, @. y& c# p! W% \, ~, |
Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。8 d& k6 d9 `6 l* L- U: w* _
& d. I! v9 {/ A1 H5 F( v z
M6 l8 z! [2 ?6 p" i' a+ r5 \5 X6 `
Matlab与C/C++混合编程的方法论
& L" \9 u9 T# |
0 p. F4 x3 C: S6 {) R3 y- R% \鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:3 [0 m6 I5 [7 b0 I
5 t& V8 d" E5 E0 @
" k- U# W, H; E2 S/ I0 i
9 D Q6 v! k1 r/ ~) b图 1、Matlab与C/C++混编方法论流程图
' f! \% s0 }3 s! o |
|