找回密码
 注册
关于网站域名变更的通知
查看: 431|回复: 2
打印 上一主题 下一主题

初步研究一下C/C++与Matlab混合编程

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-1-7 10:08 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
! }3 U2 t* \8 b3 m# R5 i' E4 j1 ?
Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。
. r( n. O( ~0 i& U3 f8 `+ B
! z+ H( ?. d- [# S/ L! G0 _     本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。
# |7 i( c& l: B/ @8 S# H4 k, Q, ]. [% e2 t4 O+ d( L
     本文主要分以下几部分:
5 H! z; @# j8 @: D
6 k  L# e) E* r, l2 V     Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。. f+ {: p  ~$ q( K" j: C5 j3 R$ S

5 m- d* a; Q) G  p, F4 A6 ?5 |8 H     Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。% x3 U( y, C  c% Z
0 r  w1 e* x' y( a; t  [0 x
     Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。
4 z# `/ e0 N! d, Y' e
6 Y% N, t# _+ Q7 m; a. f) l     关于数据存储的说明。说明数据在Matlab中的存储方式。2 i# K' U* b( x1 V" z% o' ~  @
. h: U; v4 [" E/ S2 v
     注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。
. v  a/ p1 A" Q
  w$ \" \$ F4 x( J
! j! Y) j) L! Ohello Matlab
4 L5 p* ?. N* n
     我们一步步完成一个叫“Hello Matlab”的程序。  X) P1 r8 J% N+ G% J: G
& H8 W7 e  z! x+ A0 q) o0 x) d
     第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。) {  d$ o) c8 V1 ^9 H7 _
6 N; p5 l2 a- c7 q5 S
  • #include "mex.h"
  • void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  • {
  •   mexPrintf("hello matlab in C/CPP.\n");
  • }; g2 H$ F6 Q6 i2 Y+ v5 S1 a- ]( H# l8 Z
6 }, ^% x6 ^( B1 `( P% Z' R
, v- }0 D4 |/ s
Code 1, abhimat.cpp
6 k" y: N, M7 W# B( I# p* k     “abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。6 C; ?# P* ]2 h( m8 I9 p4 j* V, W
* w8 L$ X# L4 h8 P+ Z/ D6 q+ ]
     第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。, |) I( {: X1 z$ s" u& K
/ V: b4 x3 F# y% b7 z% I0 p+ X# F
  • mex -setup* R  Z& V% k" N1 P% N9 v: m
$ U% ?' H8 n3 d1 [. {$ \0 @' g1 u- d
# ~7 a) U' n, x& c2 \( G: E
Code 2, 设置Matlab的C/C++编译环境. G6 _4 B4 y" B" y* i' H
* L- I4 }% p6 Y3 R" d" e
     完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。
, R8 P1 y1 ^3 I% ^* j8 `# ]
# q' Z( F/ o1 D! @1 K
; \% z9 f' f" V& U  r
  • mex abhimat.cpp
      d9 m0 y( X& `9 b" M

# h, }7 d  n' L2 ]' U
; [' q/ d. y9 A! h4 x6 dCode 3, 编译abhimat.cpp
$ q" Y# Z, A' \) _6 I5 ~; [! s- I; `/ t; [* F
    第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。
7 Y6 K# Y# B+ l& Y
$ P5 d. I, Q, E2 Z  F     细心的读者已经注意到了:" K& q/ L* D  j6 N. j  \0 B
7 H( N5 _8 K& X6 z& m
  • 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
  • Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。
    $ T1 d* d( T, u+ I; @" ]
% \) n! n0 C/ V$ Q, a" e
8 j/ `' H, L: j8 @! m  h
Matlab调用C/C++程序传递参数& X& ]4 u. g% Q6 C9 Z' p( o( \

  Q5 U4 u6 x1 X2 m% C    此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。3 `; Q  `6 i; W4 N/ e( l
/ Z3 D8 B' k8 A; {( I
    给出Matlab中调用C/C++程序的一个实例,如code 4所示。' i: L  s. L5 C) f$ d
# t4 @  u3 b& U8 G0 J6 k
* {2 `/ ]0 j6 e: z. m: k1 X1 q
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    2 g) P' ^7 W5 ]( M
1 X, t- \6 [. O0 G

, q$ u/ Y1 j* O) @8 LCode 4, Matlab调用C/C++程序实例4 a& [: D- O" t4 I0 c  S9 T% e
* R8 h0 P7 g" |% q- m
    下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。' v7 q0 ~, S0 ^+ Z
+ V1 I  v2 p& ]8 l1 c5 x' S% V
    注意mexFunction函数中的四个参数,一一作出说明:) m; L. ~- v) U. I+ l. a2 c

. a) o* o4 A/ r- D    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。
" y3 k8 j& A# }/ P! h  z
( U* }$ A/ y, q5 H' n, c; f% c    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。
4 W5 T6 t- K" P! Z  |; g
  P- v4 @( S! C+ Y2 N+ S) J    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。/ M- x2 F: r/ a' f8 ^4 x/ l% W
( P; y( z1 b) H: A: s/ q+ e
    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。
' U" m0 R& u9 @8 R+ _
, w: @9 O& R' W    mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。
$ J7 A$ Q( G( P) I/ l
7 ^' p# e+ P) b" r) G    下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。
/ N. k+ E$ k& j, l0 O, N  k9 x8 d# [4 U+ q9 s+ t. y& h7 n
  • #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];
  •   }
  • }7 e" m  x$ j8 v+ [2 k4 I

+ j  W6 D+ n/ a5 X8 e% cCode 5,  abfunc.cpp的实现: Z7 i4 {7 c* d- Q+ y

8 [3 Z8 o- a: J; O8 d    说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。
# t& N- W) T9 G+ ]% h; X6 |' Z% _. S4 f  }$ e
    编译并测试Code 5中的代码,参见Code 6。
+ f( e8 _: g* z% K. {) f6 t2 q( D$ ^6 k) f0 E# e
  • mex abfunc.cpp
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    0 F4 }) L" Z% Z( n! z9 w( g

( B: ^- X* ~- o; }2 Q0 d3 O
9 a0 |3 p" k/ R4 YCode 6, Code5的测试代码
$ O  D" h8 Q4 ~' d/ u6 B$ S/ o* J' ]/ L! U3 ]  b. a9 Q! O7 O. f
    Code 6的输出结果如下:6 k8 T) q, d/ J6 Q  C
$ ^# v5 z& w! I( C# _/ a8 ?
  • a =
  •      2     3
  •      4     5
  •      6     7
  • b =
  •      0     1
  •      2     3
  •      4     5
    1 ^. M) ~4 q3 g5 Z

# `9 ]* }5 [( w' i! F  p& v) }8 {' Q. Z0 N% o% s: e: l( y
关于数据存储的说明
1 X9 m2 M; b5 l
2 x4 g  K  f* G  [" h! d) u   Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。* K# |3 }' S' g- r0 I2 g

5 ^) q# |* r0 b3 W7 p2 _0 i% i: k  y5 ?& L0 ^/ R6 Z
Matlab与C/C++混合编程的方法论
" e& t: m' U+ A8 U* f( s& G& m
) G8 y2 p/ y! `. w" ?鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:
) K; b( j' B- L2 E3 t
* S8 ?8 N7 ^" p" ?; Z 5 T& X6 T! t' m( }+ u4 R! C
3 h' ?6 ^2 W$ H
图 1、Matlab与C/C++混编方法论流程图/ f9 J, k# o+ u. Z2 [

该用户从未签到

2#
发表于 2020-1-7 18:06 | 只看该作者
C/C++与Matlab混合编程
  • TA的每日心情

    2019-11-29 15:37
  • 签到天数: 1 天

    [LV.1]初来乍到

    3#
    发表于 2020-1-8 19:14 | 只看该作者
    C/C++与Matlab混合编程
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-23 22:10 , Processed in 0.156250 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表