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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
4 O* a0 |/ y* B5 t+ f
Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。4 {7 g! `! r: q% T

+ ~$ C. \+ j5 ~0 k     本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。
6 N+ G: H# _$ l0 ^$ K" y% q3 S; ]# n0 R% C. A: ]
     本文主要分以下几部分:2 F8 p( I& }8 t7 I" \
: k3 Q" ^0 K) g# J7 ]
     Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。1 S0 ?2 l" x4 e/ Z' e% v7 t

& N5 \  R/ s. G% f     Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。
5 ~8 L7 ^6 v/ D* N6 N* K; u/ t7 m
8 J7 a- d* m) n$ v+ A! [  t( T     Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。
& n5 c- s2 j- ?( m2 x) Z# a! c& H, M) X" W; F. e
     关于数据存储的说明。说明数据在Matlab中的存储方式。
# d6 n1 ]' n4 i
) ~- u$ @* d  e0 F5 k4 V     注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。/ n5 B, J! c2 N8 y9 Y

( t; R( ~2 F$ P( ^0 {# j- b  `0 L+ t, {% G4 p# ?
hello Matlab

% c6 V& ^. T! ^/ V1 {) e     我们一步步完成一个叫“Hello Matlab”的程序。5 M) W$ g0 O! H( X1 M
0 W, k9 n: w! u
     第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。. g4 c/ `5 O. p9 S8 Z4 y
* Y0 P& L! \# J! g( [
  • #include "mex.h"
  • void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  • {
  •   mexPrintf("hello matlab in C/CPP.\n");
  • }
    3 e' f+ I9 {7 Z

, o5 O  j/ {# H* W
1 y$ y% x* N6 X+ zCode 1, abhimat.cpp: {! }/ x* p' j7 G( I
     “abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。
: \! J/ h& N( O( l" j. {, h3 Z; B! J+ `/ e) [% Y# |
     第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。
" ~' e7 k9 J7 G
/ y1 \& o! [+ w
  • mex -setup/ _8 I- E4 [& z" a4 }# l
0 I& j& v* B' q5 q7 [" V9 ?
! R" i- x2 x# y  Q% D9 \, m/ P( F
Code 2, 设置Matlab的C/C++编译环境" l' [- X. D3 o# |

0 s7 d$ E6 r: a( z- v# F     完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。
" u- c' Q7 o  f0 I
2 b5 ]) e! n0 X/ |! P5 X2 K+ i
7 ?6 l% {: @7 u
  • mex abhimat.cpp0 i/ {& v, ^, P6 d* P& {/ A
7 A7 N/ G8 A/ O1 A' d% ]! s

. i8 A6 }+ z4 cCode 3, 编译abhimat.cpp  K; q7 o' o* @+ s) H
$ }9 c# R4 s3 |
    第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。
; [9 }/ h+ ?4 R& Y0 N, \" E* K5 {& |; ~# ?# z
     细心的读者已经注意到了:
% z2 [+ S4 D9 v2 s* q$ A; [8 Z
( a% C4 z- J; l# u: B# l
  • 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
  • Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。
    4 X/ D( y" Y2 ^) O% r! J
# E5 _3 Y& c) h+ r$ ]
5 C( {3 T* {! y( ~% U
Matlab调用C/C++程序传递参数: Y) e# Y5 a! z; T1 s7 }) d$ l' U
; r' K% q! e  ?% q" K4 A
    此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。/ X  B' q1 w6 ^. G( ]$ R

( F2 \6 y- [" p    给出Matlab中调用C/C++程序的一个实例,如code 4所示。
7 t. r6 L# k; V/ @" j
1 o- W2 G. _' F2 r9 p
2 }0 c0 X; `2 A+ N
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);- K6 ^( s0 R9 x

" V  T) _8 @/ \2 _! j% d5 W2 J& I/ E3 X+ z  Y& g. H
Code 4, Matlab调用C/C++程序实例1 V4 S4 f( [* a' b

. f' l: r0 V7 \8 Q    下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。# a! K  m- E( G! n) r" b
* n6 I( ~) L+ O1 i6 [+ \
    注意mexFunction函数中的四个参数,一一作出说明:: v7 m$ K+ w' ^6 F/ k$ a

- z  w3 d2 \" [7 M' q( b& |: W6 M% O    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。7 n; Z/ i: V( i$ S. \

& J7 n3 L5 }' P, D2 k    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。
$ L; N6 \- z% ~! D5 l5 L
: M( P, }1 l3 e/ ^2 c8 v    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。
/ z" w, t& R: h- v9 l2 O" I. v# c# r6 Z9 f' ]- O. {  A
    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。9 G( u& [5 n; v8 y5 d2 H
5 o: _+ H6 E) C: K
    mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。
" l9 v4 C' L% N5 Q2 _$ ~4 o. S4 ~1 N1 X7 K/ S
    下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。
' U8 S* o( o( v5 h: H& {2 D  q& L, p' l, X! Q3 S2 `! J; w
  • #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];
  •   }
  • }1 g( J- {2 J. d7 \' V
/ m# j) o. I, v  W
Code 5,  abfunc.cpp的实现
, ^2 U: y1 a; i% d$ M
6 O: t9 z+ [' E    说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。
. x" b. F. M1 L5 O6 f/ q  c/ t, {! ~! N: P# o: x/ ^
    编译并测试Code 5中的代码,参见Code 6。+ s7 l  D# B: K7 @/ T' ]; W0 b: D

  l& W7 @; J" w8 z1 Q2 H
  • mex abfunc.cpp
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    : B( y" {5 T0 T* X  g

- a3 f. ?, D* Z* y' T  a; P. W: \! H. l& ]; F0 {8 K
Code 6, Code5的测试代码9 _6 E4 ^/ W3 h8 \  r2 V

: b& c6 l0 }; G3 G  D, ~    Code 6的输出结果如下:
3 i4 i4 L3 Y( w% N
, F. Q) N1 N( a8 l( }
  • a =
  •      2     3
  •      4     5
  •      6     7
  • b =
  •      0     1
  •      2     3
  •      4     59 ]. H4 L3 C9 A7 w8 E7 P

) ?0 {1 b& g: J" m% j* X
8 |" |' p' j/ E/ o; u关于数据存储的说明2 ]( R; k. _9 X  t2 m  u- D2 v

7 x4 d8 f2 S( G9 h) g0 |. z* p4 ?   Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。
, {* @; P1 g, ^8 j! [6 z" h1 I
2 ^8 V( Y/ Y3 G0 P* f/ ~
; f+ l. F3 H: Z7 u! i3 lMatlab与C/C++混合编程的方法论, t' _# G9 J9 F9 b
. z& R; d# b4 S& N
鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:- L6 i/ G# W' \+ a0 y) b$ ~$ K

" z4 E# _1 s7 R* H6 d
; k3 j' N9 i- X) @* ?9 t) G) C
( n" \" P/ N2 o图 1、Matlab与C/C++混编方法论流程图: K/ A2 }8 ]$ N1 Z# o
  • TA的每日心情

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

    [LV.1]初来乍到

    3#
    发表于 2020-1-8 19:14 | 只看该作者
    C/C++与Matlab混合编程

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-11-23 20:47 , Processed in 0.171875 second(s), 27 queries , Gzip On.

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

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

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