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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
1 t1 v: ~3 j% P# w. F
Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。
& r( _" w2 x$ o# _. ?& ^' `
6 J1 D, j5 ^  `; N1 c0 `     本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。
3 K: u( P+ a/ i/ Q* X
, V' c3 K0 P, Q8 j# d     本文主要分以下几部分:
- P, s! I" S2 f! X; m
; R) o" A& [! S8 `3 {     Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。
' u& j! Z2 l$ d2 y1 l2 \) X1 z* M. d) ~# z8 ?3 w4 ?
     Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。6 R5 {2 x. [6 x0 E0 M

0 i4 M$ K6 E. }4 N; f, j     Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。; S9 E5 D7 q; n) }7 ?9 p

* h" w/ |+ o* p% a8 J# U5 m' V  C     关于数据存储的说明。说明数据在Matlab中的存储方式。; w4 H5 r' ^1 F6 R- w% J

* P6 t6 H* f, O5 _  w     注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。$ m, x  w9 S% M, J; M& a
8 o4 \$ _0 Q: ~2 P

% w7 z! c6 Q6 n3 W4 `0 {) b# @3 b) Fhello Matlab
1 T% j9 y2 M% E  l6 g, Z$ p, Q0 x
     我们一步步完成一个叫“Hello Matlab”的程序。# y# t1 O1 y9 q8 P+ E- u
# |3 i: T* A" S, a, ~" L
     第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。
) x& ~: u6 \2 ?6 ]0 L% Z- Y, I
5 {% i2 _! T- f. i* q
  • #include "mex.h"
  • void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  • {
  •   mexPrintf("hello matlab in C/CPP.\n");
  • }
    $ D# p6 ^) j  e5 D' Q2 {! n

( h+ o2 ^" R0 G2 m) e
# I: `5 a  f" k+ }. ?# SCode 1, abhimat.cpp
2 H- v- o2 f3 \6 Y- x$ i     “abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。3 {2 A0 }: K. |7 P
3 x: c6 D3 ~; Z0 ~
     第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。. N9 |7 f7 k7 M# C/ f1 a

' f; f3 _7 _! N2 V
  • mex -setup! A/ e5 Z  \. u  c8 @9 d% {

! g) D; Q6 ^. W, m
7 t9 G7 T1 h7 D$ ]* Y& [/ R- MCode 2, 设置Matlab的C/C++编译环境1 R6 h8 a7 t3 S5 M" A

' N( }4 n/ L  j+ Y  a     完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。2 [3 K# F8 o/ i
$ G' U/ D+ W  m# R

) M5 T9 ]% _8 J
  • mex abhimat.cpp
    7 g* i* E2 S0 ?! m
! O: }; Y2 c6 q1 M
* w* ^1 ], s7 S) r2 r; M
Code 3, 编译abhimat.cpp1 Z& C6 e. X6 a/ N+ ~1 b5 V
6 L* n8 G% s7 J' c7 q% D0 F8 L
    第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。2 e  ]7 J; B, h
" {( r4 k5 c4 j8 }+ k7 R
     细心的读者已经注意到了:8 n7 [' P: d3 x6 f

* u- A' }4 g: v. Z- w" H# H
  • 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
  • Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。
    9 l& T# X7 o1 V4 \& D, z
7 N1 _& k. j3 C: D0 S4 u( s$ l, c$ E
. b. Z0 W+ V6 A, \6 z) w
Matlab调用C/C++程序传递参数2 {4 q/ v, I* Y9 K+ b7 g4 F( D
6 D  B9 W# e8 |" O; c- M+ w
    此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。# L% n' n" J$ A1 X4 D' O( Q: u

% ~' x( \6 Q% Y6 P    给出Matlab中调用C/C++程序的一个实例,如code 4所示。
7 }+ Q; g' i' O/ L" n( K* w
8 i; b6 m; n/ d) M+ ?5 f5 Z
3 x- v# }* C- y, f9 E- C8 B
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);6 `, v7 v$ H' \# W, u

7 u7 a) L) v6 X% }; C6 w8 ~5 `: M7 T1 c8 ]* B
Code 4, Matlab调用C/C++程序实例
& U* \6 U  H2 P+ r6 L
, h0 T8 G5 ?& V3 \+ q    下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。
  F- d' U& `3 d0 }1 D) G) V1 q' J7 I
, c8 k: Y' K4 `6 a    注意mexFunction函数中的四个参数,一一作出说明:+ G# _5 `# A5 M! X% d
. S# ]. p7 h" [3 M3 L
    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。1 ^$ S( t4 c8 Y& i; D" \

# D. ?1 E1 F8 g! Y    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。
- y, P* u, U0 ^/ e0 D5 `
/ P% b* c+ Y  M- ^    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。3 h7 u2 Z# n& c7 _3 c  X
+ E7 \# _! K- f1 c& J4 l* Y2 \: o
    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。
8 X6 V9 p4 I  f# ^. m3 z& y: T) I4 Z1 X& {; ~3 i+ Q, L9 P
    mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。9 a+ U+ x9 C+ H
7 o* N  j( S+ g2 `& {
    下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。, g4 c( ]5 `: z
3 E! h! I1 C( y' U8 j1 o( i
  • #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];
  •   }
  • }
    $ g0 e% u  Q* Q+ ?- |& Q3 v
. d( J7 Q( x, D3 ]
Code 5,  abfunc.cpp的实现
( O9 @3 ?4 {3 F( s
+ \4 |0 U* Y. i8 t% c3 |9 P    说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。
- ^0 c* o% d# F: l2 y& \, ~' i  ]% f3 i+ @# c5 L/ B+ P
    编译并测试Code 5中的代码,参见Code 6。# {* z3 y' g0 K4 k
* i" ^& e* d( u9 w% g) M
  • mex abfunc.cpp
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);- u  |5 c! W; q+ H6 t: p5 w! H

) [+ Z/ ]% _' p, W
( Q& ^% q/ q* t0 B0 XCode 6, Code5的测试代码0 Q2 F/ y2 J5 E' F  ~% ?
0 \0 b- V& F3 Z+ {
    Code 6的输出结果如下:
- C7 u' d) W, |; W* Y* i" @& @3 n2 u* @/ J+ d, |8 R+ U4 g! u
  • a =
  •      2     3
  •      4     5
  •      6     7
  • b =
  •      0     1
  •      2     3
  •      4     5, c" ^( `  Z- j  s7 Z7 L! {3 t

& g8 [: Z: a, t3 C' `
/ u1 k: A% L. e0 g4 }关于数据存储的说明) \) ^3 l& d% Q0 D
0 Z$ U. k7 F8 I2 v. b
   Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。
. S+ }) |! ~: |/ s3 o" C
3 ^9 \2 Z: P/ O/ g' R) {. G. I  C3 j2 z1 M/ k: b( w
Matlab与C/C++混合编程的方法论
% f6 o$ e4 h5 h; d3 a2 F# A" K6 Q# ]) ]! {* x9 L* ]5 M
鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:
' X7 V" s. j+ P4 S7 c
1 G! P- r- G* c' {- Y
+ Q) ~) k: y& l! d
  f0 v3 W* U9 n2 V图 1、Matlab与C/C++混编方法论流程图
  W' O5 O: v7 m# N5 r( F

该用户从未签到

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-1 20:27 , Processed in 0.156250 second(s), 27 queries , Gzip On.

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

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

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