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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
" I" j2 Y! B' H9 K8 U
Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab实现我们的实验程序,用C/C++来实现Matlab程序中比较耗时的部分,从Matlab程序中调用C/C++的程序以实现加速。5 D+ c, |1 P- R. b
9 f" Y/ J' }) f* L- q( n6 J
     本文主要讲解如何在Matlab中调用C/C++的程序,以及如何编写可供Matlab程序调用的C/C++程序。! u+ ]% N- h  G+ e3 T) [

/ V# t: _; L/ W# V1 ^! f4 l4 Z3 z. Z     本文主要分以下几部分:0 ?  y7 g2 R  X6 W0 L

$ O8 W6 T4 z- X7 Q! g     Hello Matlab,用一个简单的例子来说明如何在Matlab中调用C/C++的程序,以及可供Matlab调用的C/C++程序应该注意哪些基本事项。& a  r; ~. N* n" ]

9 w0 V/ K5 u" i* d9 Q     Matlab调用C/C++程序传递参数。讨论在C/C++中是如何使用Matlab传来的参数的。
; h% q8 ?2 V5 W" ?+ L! Z$ t4 r+ e' s+ {: b+ Y5 L
     Matlab与C/C++混合编程的方法论。给出在一般情况下使用Matlab与C/C++混合编程的方法步骤,让大家有一个较为清晰的应用此技术的思路。
/ s' w1 m$ F; ~) i  g& @7 c2 H
: _. \( D& I3 @6 f2 ]/ y3 ^     关于数据存储的说明。说明数据在Matlab中的存储方式。4 J# w, t! Z6 o# |! @3 \

6 e9 q: G- C. `! |1 r( S     注意:本文认为读者会使用Matlab,掌握C/C++语言,并且有一台计算机。计算机上安装有Windows的操作系统,操作系统上装有Matlab以及Visual Studio(比如VS2008,VS2010等)。或者计算机上安装有Linux的操作系统,系统上装有Matlab,GCC。
) H- Z" u- L; f% n  Q" i, N
; ?" K1 D3 j. s$ W* s) d. [# O; D2 |* z# X$ H4 B( A
hello Matlab
% D3 R& V  A2 L& H0 H, |3 Y$ I, d( r/ b
     我们一步步完成一个叫“Hello Matlab”的程序。7 r6 ?" E# G4 V4 U
* y% U5 }" r; ^1 W: x1 [3 l
     第一步:在你的计算机D盘下,创建一个目录命名为HiMat。在D:\HiMat目录下创建一个文本文件,命名为“abhimat.cpp”。将Code 1中的代码拷贝到“abhimat.cpp”文件中,保存。(注意,这里建立目录以及命名等行为不是规定的,只是为了讲解方便)。1 I. O0 e9 m, I8 z2 f
7 e  Z3 X4 A+ |5 W2 F; b1 A3 s6 T
  • #include "mex.h"
  • void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  • {
  •   mexPrintf("hello matlab in C/CPP.\n");
  • }+ b  O1 o1 ~1 T" a" G! m9 i
# S( y( B$ k# u9 e

; v1 }1 V* {- p2 PCode 1, abhimat.cpp+ ~! i, V# s$ |0 H2 d
     “abhimat.cpp”就是将要在Matlab中被调用的C/C++代码。- Y! K: w: @) m! V  k! z

! _* B0 @( k* O4 V1 e  _; c3 Y     第二步:在Matlab中编译“abhimat.cpp”。启动Matlab,进入D:\HiMat目录,在Matlab命令窗口中执行code 2中的命令,根据提示完成C/C++编译环境的配置。注意:如果你有多个编译器,建议选择最新的。
9 ?8 u( A$ g3 F  D3 h7 `
( O% u2 w, X: \, G* x$ {: A+ U
  • mex -setup
    ( a7 a# N- Q9 L! [

( l' z) X0 m0 y" B' ]& J* z
$ X3 x7 F/ D) pCode 2, 设置Matlab的C/C++编译环境
! |* N% S  U* C* V) J7 j+ x. g7 V% T( w
     完成配置后,在Matlab中执行Code 3的命令来编译abhimat.cpp。
# P1 u! S7 T! A, \& n
3 }7 L0 R$ ?3 P4 d2 q+ T' a4 l* V- o  y( p9 z6 k4 s) z
  • mex abhimat.cpp; Y* [. [) d& T

6 `/ \& Z2 H& O. [4 t# q7 ?6 p) b( r- F. q5 c: U8 t* H
Code 3, 编译abhimat.cpp! M' A' x0 }2 ~& Y0 P: g- q7 _
* n5 x! {, D1 ~$ b6 p
    第三步:执行编译后的C/C++程序。在Matlab命令窗口输入“abhimat”或者”abhimat()”,都可以调用编译后的程序,推荐使用后者。
0 X$ ]% t9 v4 q! e0 m7 _2 B8 ^- d# n: s$ u) u+ V, c0 z
     细心的读者已经注意到了:+ d" G) w* V' U6 H0 T

5 {# d9 |  d- p. Y) C; R( S4 v0 O
  • 在Matlab中调用的C/C++函数名就是编译后以mex*(这里,*表示任意多个字符,例如mexw64)为后缀名的文件名。
  • Matlab执行abhimat()命令后,实际执行的是mexFunction函数中的程序。$ n) L* C* q! V; ~! J) V/ [. j3 g
6 {/ \9 u) B; @- I( Y

0 \: i: |+ U  R" M2 BMatlab调用C/C++程序传递参数' |2 ~) l3 R/ g0 t4 I

' k2 s7 H) D3 c0 d    此节我们讨论下,在供Matlab调用的C/C++程序中,我们是如何知道Matlab调用的参数类型、个数的。4 K- I3 q' ?1 B2 H1 j! y  \* s
; r8 N8 `9 `6 `: E
    给出Matlab中调用C/C++程序的一个实例,如code 4所示。2 e1 j" Y2 T2 r8 t/ X7 R5 T

1 [8 c' h% f2 b; R( m7 v! t' U4 @
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);
    + N  T, q3 _7 d# ^+ j2 X
" d' w, n! C+ l0 b2 }& d" D
" u* x7 d: z5 c0 w  W! ]. p
Code 4, Matlab调用C/C++程序实例
6 a! Y$ S- r+ `  z8 Z$ Y  p
; {' w1 L. }1 m, v# g0 r2 s9 R+ n    下面的工作是如何在当前目录下一个命名为abfunc.cpp的文件中实现mexFunction函数。在这个函数中如何获得Matlab命令中的c、d两个变量的值,如何返回a、b两个变量呢。6 J" b" E% D. D+ W! ~3 S% k% \$ u3 D
* T& |5 L5 H9 _" H& i
    注意mexFunction函数中的四个参数,一一作出说明:
0 W5 }) D7 H1 a- d1 z& a& y
# ]( H$ m) y- b- T! S# W7 ~6 J    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。例如,code 4中的调用,nlhs的值为2,因为它的等号左侧有两个变量,他们是a和b。7 [& T) X% V8 c. n- ]1 e2 ~) _# P- o

: q: T2 I% G7 s/ I    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。例如,code 4中的调用,plhs[0]表示的是a,plhs[1]表示的是b。
/ T. }/ E! a3 v% I& J2 r2 w5 ~& B2 T8 T8 E) L3 }3 E
    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。例如,code 4中的调用,nrhs的值为2,因为它的等号右侧有两个变量,他们是c和d。* I$ w9 X' ?$ P% T5 t5 L

$ k% {7 L+ C! f  R6 ]0 D    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。例如,code 4中的调用,prhs[0]表示的是c,prhs[1]表示的是d。
5 Z7 s. Y8 Y  Q1 R/ v+ |; @0 |* g! J
    mxArrary是一个不可见的数据类型,是Matlab定义的,大家只需要知道mxArrary的指针与Matlab中的变量一一对应就可以了。
/ w, r7 b2 {  U4 Z! [4 m1 b/ F
3 W$ P! i7 y7 L- Q% d* v  G; ^, L    下面实现abfunc.cpp,功能是a=c+d; b = c-d;具体代码如code 5所示。1 Q. l! S( C2 ^

% p) I$ q5 l! q0 C+ z! X, H
  • #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];
  •   }
  • }% k0 h- [2 b& N( Z
6 R) m0 H  G8 t: C& I" g9 T( \+ ^
Code 5,  abfunc.cpp的实现
& ]  B; q- T# l1 R* D" j% a$ d3 A) Z8 e1 I
    说明一下code 5中用到的函数。这些函数大都以mx开头。mxAssert是断言,类似于C\C++中的assert。mxGetM获得Matlab传来的变量的行数,mxGetN获得Matlab传来的变量的列数。mxCreateDoubleMatrix创建一个2维的Matlab变量,形参分别用于指定变量的行数、列数、元素类型(mxREAL表示实数,mxCOMPLEX表示复数)。mxGetData用于获得内存中数据块的首地址。- d0 C& G" [) ~  ]

4 w7 Q, s- y( v+ q* b    编译并测试Code 5中的代码,参见Code 6。1 M$ {: O2 v. y/ q

6 e) C2 p, ~; {# g: i" O$ r) R
  • mex abfunc.cpp
  • c = [1 2;3 4;5 6];
  • d = [1 1;1 1;1 1];
  • [a, b] = abfunc(c, d);, }  o8 I6 |* F& _% j# K- b3 v6 S

0 N8 _' h. \9 `4 ^6 N8 X0 t
8 @8 ^4 `4 ]2 T" V' C" wCode 6, Code5的测试代码
% O  }* p( _- P' N/ E) r8 H8 T$ v" R5 M- n8 @2 B& ]( @
    Code 6的输出结果如下:+ T. o/ t/ j6 g5 O. K
6 o) ~" ~: ^+ J& G4 @: c! O6 f
  • a =
  •      2     3
  •      4     5
  •      6     7
  • b =
  •      0     1
  •      2     3
  •      4     5
    7 `9 K" H! }0 a4 r2 }9 y

+ e* k$ U0 O& h
) L: `  _3 M% V5 E5 Q  `关于数据存储的说明
6 Y" l  p3 Z. O; U: x; P& r( F
: \( j# b$ k3 }& {2 K$ c   Matlab中的数据是按列存储的。例如,a=[1,2;3,4;5,6],a的数据在内存中的存储顺序是:1、3、5、2、4、6。在C\C++中使用Matlab传来的变量时,一定要注意数据的存储顺序。0 F8 T: M6 ]/ |+ l+ [
5 \. L" {6 m/ p* M
% G6 q2 O6 y( R8 B8 ?
Matlab与C/C++混合编程的方法论, [2 q5 |7 d% D: ~+ t8 f7 C

5 T2 u( r3 l2 R鉴于@编程小手 的建议,添加一个关于使用此方法的方法论流程图。希望它能让各位明白在什么情况下可是使用这种混合编程的技术、如何一步步实现。参见图1的流程图:1 p1 ^! I  i0 l5 j

+ D/ y* s: W1 x 8 T4 N4 j4 A1 x- C) Q4 z

: Z9 {5 P4 M5 t1 W& P. b: H( r1 \$ `图 1、Matlab与C/C++混编方法论流程图
5 r8 j0 {* G8 P# ^& c3 W, w! G

该用户从未签到

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

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

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

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