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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x

3 |7 n7 P% e, d, T8 T+ g- ~ Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。
4 K' g+ A; C2 T. d% c0 c3 _1 q6 \7 W
- B, ^; T8 W2 C+ p- l6 R" D+ V' m     本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。
- Z+ V6 s0 i2 l7 K" Q' d
/ M0 D( ^% N- G8 ^# a" U. t) _" Y" p     本文主要分以下几部分:: f1 D8 s% d! q" ~

2 y% ^( G- d1 M     Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。0 b$ E& ^# v5 U, h! y# y  D$ v

$ H$ c; U% `  t     Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。
" g  q( \; L8 r" @# _
( o, |& J+ l1 P     Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。
( u) f# B/ }$ ?: o  x6 `
" X( }8 g3 z- k     关于数据存储的说明。说明数据在Matlab中的存储方式。
  ]/ X! t5 ]- d& l& V; S" k7 I
" L4 ?& R1 [- c) Z/ U. n' B     注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。
) x; U: j8 k# g- g  D( J+ G9 ?( Z
% [. r9 U3 x3 Y4 k0 u8 [% H2 ?( M; r$ u
- Y+ f' ^5 H2 Khello Matlab

- |. T2 M! K+ D5 b8 Q% A- K     我们一步步完成一个叫“Hello Matlab”的程序。
! a1 a' r+ O, z- a% H  U0 c$ E$ [3 D/ M4 o3 v
     第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。6 ^4 k+ L: j& t6 c2 V5 m- D

% `/ o5 N$ C0 k4 c2 L! U" A$ h
  • #include "mex.h"
  • void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  • {
  •   mexPrintf("hello matlab in C/CPP.\n");
  • }8 \: e4 ~" L, w! ^

4 u! E1 w4 r7 w2 v% ^" w
7 U- G. M9 f: J. ^Code 1, abhimat.cpp" I! r! U+ r5 d' ]0 J' p; F
     “abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。/ D0 a4 C% `: s9 a. p& y$ M
6 N5 E( c7 q2 `$ X
     第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。- p: D1 X' G0 Z
  m" P( g1 _- c/ ?$ W  `% n8 U* U' N: z
  • mex -setup
    6 q  h5 F2 T7 }) ?- u1 g+ `' ]. b
* ]0 ^, U+ L6 M) f, _: k

7 c7 I  [" I6 M7 [0 ACode 2, 设置Matlab的C/C++编译环境
# ^$ L- S/ [2 c" H( k, T! A: V, v  Y4 V- n" y+ x
     完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。" C( o" a: ^" v7 g2 N. m7 O
# l( Q& c/ Y8 r/ n. Q) _
0 G  t) P% f3 q
  • mex abhimat.cpp
    ) z) d6 t5 H- Z' _- n2 X! L) b! }* g& R

( e5 p( |1 a1 j9 P% v: d6 x) d
( Z4 d. h3 G: e  n& }) U. MCode 3, 编译abhimat.cpp* `# H2 m5 @: d6 D/ P) u, r; ?2 N
1 `6 V9 Y6 a+ O! ~; A& @, ?
    第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。3 `8 Q  o  F1 q: |/ K5 k
1 o. a7 K1 @% H' o* P
     细心的读者已经注意到了:
! \8 r8 ^3 e6 G1 i% A- A
4 d0 P0 D' P) [- I$ K
  • 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
  • Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。
    + G" M/ ^( m9 P) k* U1 Q

% f! a" l5 r, n8 ~7 I, N1 P% c
9 t4 P, J0 j# D1 ~, GMatlab调用C/C++程序传递参数* c3 a9 t2 W8 F/ B; D8 [
/ T; p4 N! ^) u, u2 P  K
    此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。
$ j6 ?7 @& g2 {6 a! X' r- u* u: G+ v$ n
    给出Matlab中调用C/C++程序的一个实例,如code 4所示。
+ L: z& Q  {2 L- ]' X7 F& S' w
. j+ z& x; T- e+ B2 H# \0 ?5 k
1 ]( E1 K9 I8 l9 l  Q! `
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    7 R0 P5 |5 x: w8 `0 k3 H' a
2 K3 j6 X+ a' q- F- q" U
# x6 ]! y% K$ J. G- o$ Z- e
Code 4, Matlab调用C/C++程序实例3 B0 S* ?# |6 Z6 \$ Y. a0 V
7 u' d" [4 S/ e: Y
    下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。7 {* E. r0 ]# T6 K
) b7 x7 L1 l6 D
    注意mexFunction函数中的四个参数,一一作出说明:) H/ t. T# ~% E- o2 R; \
; Y' A! r3 U; s3 u( S! O
    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。7 m4 q) O$ s6 b  u% q/ u* ^8 M* j
9 ]. Z# s4 ~7 O) s4 B  Z( D3 f
    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。
, V) h# n; l6 Y# d: p/ g  g' @0 G
: h$ V! d( v* X8 b    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。
+ L" Z$ m- Z! `, l, Z
% `8 ^( C8 E7 q% n; e+ w4 l2 r    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。
( t1 l& b2 s& c; ~) o- R1 W% ^9 R* P9 y8 E7 H% g" L
    mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。
) Q: _- k- C. i5 y( M  h* I4 M9 ]5 J: u1 T- K5 J
    下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。  f9 j! q: C! B# M) u* B

9 t; @* M+ I9 N6 x- @% o% [( Y
  • #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 r4 t1 |4 M0 p0 H1 h+ W* T4 B

  Q5 }9 J( o* c9 p5 r: ^8 ECode 5,  abfunc.cpp的实现! f8 Z5 K/ u! [6 `

  r1 r4 f% K9 i1 w- ~! M( R1 |    说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。
2 Z. W# r; a% T  {+ L7 w- Z2 |8 i7 O1 K
    编译并测试Code 5中的代码,参见Code 6。) ?* e5 e  F/ r- B
3 b% X  \- C" B
  • mex abfunc.cpp
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    8 E/ R, U- p1 }" K
/ @6 V; j0 c) O4 ^
; Z3 K0 C4 z' [. z% \
Code 6, Code5的测试代码2 ~* V' S" T+ a" y, s% K

/ O( g- {3 j) t7 M% p- w0 a% u9 S    Code 6的输出结果如下:
1 h. d& h* T; X& ?  F1 i
8 N# ]% a! q% ]
  • a =
  •      2     3
  •      4     5
  •      6     7
  • b =
  •      0     1
  •      2     3
  •      4     50 k8 E/ X. d2 j
5 Z6 L  R; j0 O. ]

- u4 x# L0 c5 ?+ O+ y8 |6 K关于数据存储的说明
  z' J7 L1 k) |" h+ {: S) o! r' P- Y/ {; X; [" j% E" t
   Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。
$ Q% s; y& x/ V9 @& w! N
8 o2 `  P" P: t% Y
- T3 V% @; j6 U- Z' N. H+ ZMatlab与C/C++混合编程的方法论
; X' J1 x* }# p8 U; _$ G4 X" j5 k1 V( ?3 `, L7 t" o
鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:6 Q; e3 M, A& V, ?5 t
. Y- W# W# m* ~/ ]# J1 |  E
$ y/ C$ T+ H% R$ l
7 X; u  ?% r, ?1 U% K7 i
图 1、Matlab与C/C++混编方法论流程图8 G- _) o! Z" Z& O: l; d9 k

该用户从未签到

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-7-21 01:20 , Processed in 0.125000 second(s), 26 queries , Gzip On.

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

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

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