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

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

[复制链接]

该用户从未签到

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

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

该用户从未签到

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-24 01:14 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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