数学建模社区-数学中国

标题: Matlab调用c程序 [打印本页]

作者: 梦溪517    时间: 2012-8-28 20:47
标题: Matlab调用c程序
/ ?' J/ x8 h8 g+ i8 A+ J# X
Matlab调用c程序9 E! w5 G0 H/ `# e+ y7 T& [: R
文章来源:不详 作者:佚名
! m; _2 R2 P+ k$ o' o
. ]/ D# I  }) S6 l; X1 K: `7 b--------------------------------------------------------------------------------
/ ]+ z( f% b9 Z0 S, m
. A1 b( l( C6 b9 B/ D1 V该文章讲述了Matlab调用c程序.
* h% G5 A* V. t: v. s/ z 4 S9 a3 @! T6 i4 k: b
方法:
+ v. }+ u: [; l第一步:要先在matlab中安装c程序编译器,步骤如下:% t( h2 [2 Z# L) h$ D) P
键入命令:mex -setup# V2 Y$ }( A: D( K5 I( @
选择c/c++编译器;# q. ]" ^3 G/ `9 ]# V3 d
选择c/c++编译器版本;
: S/ i! M2 {# }/ f确认。5 Q3 |( S7 T9 y. l
第二步:键入:mex *.c
/ B8 J) }7 t& Q" N& q& B
. [! _9 U/ C& Q- F; j' C*********************************************************************************************************************************************
% U+ a! {: I# g/ s3 T! r2 A( ^; g6 W* T, x4 j) D& b7 c
实例介绍:【转】
8 O7 x5 Z* A* q- g2 y/ `
# @  C8 m+ X  _1 H& W) A如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:
6 y& d' Z/ O/ S+ G, hdouble add(double x, double y) {
$ v* C9 S* t& p3 s7 v3 Y return x + y;
) Q8 l/ l/ N0 f}
' |/ S5 v9 i  A7 m. L* Y现在我想要在Matlab中使用它,比如输入:
2 o) n$ W7 n, r0 R7 O, t' C1 b6 ]>> a = add(1.1, 2.2)3 [  H3 M( v' U
3.3000
& Q' W2 C' v! t要得出以上的结果,那应该怎样做呢?  d5 k1 H/ l7 ]3 B
解决方法之一是要通过使用MEX文件,MEX文件使得调用C函数和调用Matlab的内置函数一样方便。MEX文件是由原C代码加上MEX文件专用的接口函数后编译而成的。
7 B4 P/ |8 m2 }1 e7 n" }- r可以这样理解,MEX文件实现了一种接口,它把在Matlab中调用函数时输入的自变量通过特定的接口调入了C函数,得出的结果再通过该接口调回Matlab。该特定接口的操作,包含在mexFunction这个函数中,由使用者具体设定。
1 t8 L/ _) r8 b9 W- a所以现在我们要写一个包含addmexFunctionC文件,Matlab调用函数,把函数中的自变量(如上例中的1.12.2)传给mexFunction的一个参数,mexFunction把该值传给add,把得出的结果传回给mexFunction的另一个参数,Matlab通过该参数来给出在Matlab语句中调用函数时的输出值(如上例中的a)。, b0 k4 e+ |: q* k
比如该C文件已写好,名为add.c。那么在Matlab中,输入:: [: X1 V+ h9 m: P( n" W! t
>> mex add.c
7 L9 H3 g4 u9 N6 R就能把add.c编译为MEX文件(编译器的设置使用指令mex -setup),在Windows中,MEX文件类型为mexw32,即现在我们得出add.mexw32文件。现在,我们就可以像调用M函数那样调用MEX文件,如上面说到的例子。所以,通过MEX文件,使用C函数就和使用M函数是一样的了。8 I+ a0 ?3 Z2 x; `. C8 j
我们现在来说mexFunction怎样写。- q7 p* ^8 P$ }- w# k
mexFunction的定义为:$ W9 Z1 x5 [2 t- e8 `( \3 q8 v
void mexFunction(
+ [. F2 |3 E# |0 T* `9 F$ {* @" C     int nlhs,
$ R  m0 j9 K6 O& ?     mxArray *plhs[],
9 Z) U7 T8 i& K; ~' l3 B2 ?8 c+ l2 i     int nrhs,& r- Z" k3 B( k, t9 G, S
     const mxArray *prhs[]) {
  W% o6 Y4 Q. k* r* G4 o- k- U3 u3 H/ C# l! Z/ \
}
* a+ V* _, ?& ^' K$ [可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时:
. @4 Q$ U* m$ O6 s/ x; y8 h# F, I>> b = 1.1; c = 2.2;
( @. F2 J" b, V( ~4 r>> a = add(b, c)' G5 H9 h# ^* I2 r- o; i' ^
mexFunction四个参数的意思为:3 X: `5 g  V; W; K. m2 j
nlhs = 1,说明调用语句左手面(lhsleft hand side)有一个变量,即a
7 }4 v) Z3 @( F& ~5 I! ]) znrhs = 2,说明调用语句右手面(rhsright hand side)有两个自变量,即bc" P0 e% O% l$ ^! H% j0 I& H
plhs是一个数组,其内容为指针,该指针指向数据类型mxArray。因为现在左手面只有一个变量,即该数组只有一个指针,plhs[0]指向的结果会赋值给a4 ^8 R% s. q$ |; f+ @
prhsplhs类似,因为右手面有两个自变量,即该数组有两个指针,prhs[0]指向了bprhs[1]指向了c。要注意prhsconst的指针数组,即不能改变其指向内容。
" r; v5 k) T; b- f! q5 x因为Matlab最基本的单元为array,无论是什么类型也好,如有double arraycell arraystruct array……所以a,b,c都是arrayb = 1.1便是一个1x1double array。而在C语言中,Matlabarray使用mxArray类型来表示。所以就不难明白为什么plhsprhs都是指向mxArray类型的指针数组。
& |! T1 p3 E  M+ V9 \# `完整的add.c如下:
; Q7 {0 B; E- O- p8 ]// add.c
" r! z7 W9 x4 X# y#include "mex.h" // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数
  n1 \( n7 L9 r0 H: {8 M  \double add(double x, double y) {9 ^: }7 r% D2 c% F- ~
 return x + y;
% }6 Z% b5 a' i/ k} // MEX文件接口函数. U6 X, [' K' y- ]! N4 X  @8 J
void mexFunction(/ @1 J1 x2 p7 K
 int nlhs,
6 p* K" \- K' H/ r% I* ~: v! X1 }2 i mxArray *plhs[],  Y" N/ I; k& U. H7 K0 z& b. B: ~
 int nrhs,2 I( z& B3 `/ w% E7 O% T3 ~
 const mxArray *prhs[]) {
5 D# D# R1 P2 L+ D double *a;& Z% X8 b8 R) i: K9 U
 double b, c;* l8 D, T' B0 H
 plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);6 O$ _( b7 g& ~
 a = mxGetPr(plhs[0]);) w  W2 D: f& x5 G
 b = *(mxGetPr(prhs[0]));
' ~# C$ w$ W8 C+ d, i/ S c = *(mxGetPr(prhs[1]));" P3 \& a# U1 ]4 Z( u
 *a = add(b, c);$ i6 ?' g* ?; v- G. V4 f
} - y3 r. N4 Q8 b8 Y0 L
mexFunction的内容是什么意思呢?我们知道,如果这样调用函数时:
6 s8 w6 M% e# C" |" b2 T* _>> output = add(1.1, 2.2);
/ t2 i$ z( |; v! R* p4 `在未涉及具体的计算时,output的值是未知的,是未赋值的。所以在具体的程序中,我们建立一个1x1的实double矩阵(使用mxCreateDoubleMatrix函数,其返回指向刚建立的mxArray的指针),然后令plhs[0]指向它。接着令指针a指向plhs[0]所指向的mxArray的第一个元素(使用mxGetPr函数,返回指向mxArray的首元素的指针)。同样地,我们把prhs[0]prhs[1]所指向的元素(即1.12.2)取出来赋给bc。于是我们可以把bc作自变量传给函数add,得出给果赋给指针a所指向的mxArray中的元素。因为a是指向plhs[0]所指向的mxArray的元素,所以最后作输出时,plhs[0]所指向的mxArray赋值给output,则output便是已计算好的结果了。
, l3 W( e( o8 h2 R. q8 l- D上面说的一大堆指向这指向那,什么mxArray,初学者肯定都会被弄到头晕眼花了。很抱歉,要搞清楚这些乱糟糟的关系,只有多看多练。  |9 \5 O5 l  `- ?5 F( e9 t& m
实际上mexFunction是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保
  m1 A+ A% z' ]输入正确。如在add函数的例子中,用户输入char array便是一种错误了。: B0 X: K# J4 \$ A% R
从上面的讲述中我们总结出,MEX文件实现了一种接口,把C语言中的计算结果适当地返回给Matlab罢了。当我们已经有用C编写的大型程序时,大可不必在Matlab里重写,只写个接口,做成MEX文件就成了。另外,在Matlab程序中的部份计算瓶颈(如循环),可通过MEX文件用C语言实现,以提高计算速度。
% ^6 P2 Z: S+ Z! E# g3 J1 a0 T4 Y" P8 m  S' T
*********************************************************************************************************************************************- K- [8 k7 W7 Z5 x/ ~7 s

1 b( J4 H, V; M! Hmex 的目的,/ Q1 ~+ O+ M; o9 |( B/ j' w
$ l3 b% ~1 _6 ~
通过C/C++语言编写代码,Matlab中将其编译成mex文件主要可以做以下几方面的事情:
. k8 v/ P0 A) K" m7 w+ k3 M  a0 p  m% \1 a9 a% J3 G
1、加快程序的执行速度. Matlabfor上如老牛拉车的速度确实让人抓狂.* l1 D; p/ I: x5 z9 G
; G7 O& A. f) t1 i
2、将Matlab作为C++的开发调试环境.尤其是有大量数据需要处理时,Matlab观察其中间结果十分方便.
, f; t) J4 j, L7 C4 h) X$ E9 k- y+ s% \
3、据称可以弥补Matlab硬件设备接口的薄弱环节.
& [8 J& E2 s7 S$ d
! f" `' A1 O5 Q0 p$ ~* x今天写了第一个使用MEX.
( A% Q5 l% p( H
1 Z5 B% v# t7 d; p3 z) t- n' K" t一个简单的对Matlab普通数值矩阵的操作.% W8 J  Q* i8 n: l0 g
- g! g9 H. e* n9 \
其中Matlab规定的与操作系统版本有关的mwSize,mwIndex, size_t32位系统上其实本质上就是int,所以/ O$ ]9 ]( P) Z' j, t4 b8 z# r

+ i; e/ @! ~9 P! `. P& V一律用int代替.
  U) Z, F! B) j  o3 P% z8 d- j# b: [) y/ z
#include "mex.h". y! d: y$ E6 Q5 M) K& b! P
#include <iostream>
; [% t, A9 L7 }) e; y9 p; B1 `. H
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]): g) j8 _) K1 n* O1 {& @6 y
{7 c2 U8 S/ q' x% m

7 x: H' J% b( i- qint i,j,k;
# p6 W- n9 }8 E2 G7 M; }int index;
4 x$ O$ X" x7 S8 N6 P" S+ f  P$ Kdouble* pr=NULL;+ [  M2 @" _* M$ _* ?/ o
double* pi=NULL;
2 X# ?8 \0 y3 \% }/ Eint M,N;
" E4 ~- H# q8 w" W3 P4 f2 qint ndim;! L: a. q, V# g+ A2 K
int dims[2];2 Y) i6 @- ^3 x6 V* x1 [+ T) n
for (i=0;i<nrhs;i++)
* F) F1 h2 f- x1 R6 U" L1 N% J0 D{% z5 ?6 d9 Y" a/ j
   if ((mxIsDouble(prhs))&&(mxGetNumberOfDimensions(prhs)==2)), d1 ~8 t" C( e9 [3 A- T
   {  @8 y# h# k+ {) j. q* i
    pr=mxGetPr(prhs);
0 L% A) S3 t7 N  N9 @    pi=mxGetPi(prhs);7 L( k* q3 |- |6 k: C5 Q# w8 A
    M=mxGetM(prhs);$ L% V9 |: G4 T7 P; f. y5 T6 K8 N
    N=mxGetN(prhs);
" E( O  Y! c. k! B4 |  U    ndim=mxGetNumberOfDimensions(prhs);
3 B# R$ e5 I9 F: I" U! a" i7 _2 T0 j
    mexPrintf("变量%d:\n",i);" f. D4 q$ Z) a. o8 Y
    for (j=0;j<M;j++)
+ n$ d. k$ ^; o    {9 i, E8 u9 I( V& t5 g3 Z
     dims[0]=j;4 X: d) l6 ~: v1 m' B. o* N
     for (k=0;k<N;k++)
! m& ^  h+ ]* k5 H     {* y1 z8 b" i: Z' z1 M
      dims[1]=k;! y& G& d: @+ |5 k2 X  @
      index=mxCalcSingleSubscript(prhs,ndim,dims);
  a# G$ k/ ?9 T3 c, h3 {      if (pi==NULL); C, O+ ~! P) L! y5 k
      {
0 d/ Z! G! o! `/ S& ~. E  t$ i' [       mexPrintf("%6.2f",pr[index]);1 }. q- H+ }/ ]4 t! ]7 q* W8 q# F
      }( t+ J- |+ x& P; j  R' k; U) ~. {5 q
      else{; @% B1 l& P8 w' E/ s0 I
       mexPrintf("%6.2f+ %6.2fj",pr[index],pi[index]);) J* p' a* \9 N: T8 B8 y  }% F  I8 e
      }! Q5 {' F+ _% \9 E7 A0 L
     }
; M% u- K- A5 X4 a     mexPrintf("\n");
1 t& q7 }! ~2 v6 V2 P  n) _/ }  r3 @! e+ N1 ]
    }
! T. N1 N3 Y* v+ ]  # C" T( V" `5 K
   }
- W4 c7 B$ O; Z0 \7 }3 h  `   else{) _1 P# h! z3 |/ p, I- }0 Z
    mexPrintf("input NUMB %d matrix is not 2 dims&double numerical array\n",i);
/ z+ o+ ^- V; `: L}9 m. j7 ?5 D0 V: I  N. M6 W

  @6 s/ _) \; r3 B) W& R2 j/ b1 |' ~( M7 N
}, i0 e6 N+ W3 o9 v& Q2 i$ g% P
: u8 \2 S; Z0 @  {5 u
}
9 K2 h& `4 e  N5 W8 v0 d" v
5 v5 i  o. c$ r/ l0 }Result:
9 u$ a  ]* X9 f4 z3 w. w  z( I0 s
1 l0 i% k. h- }9 {>>mex test.cpp) J( O# y8 i) ?8 ?
>> test(a,b,c). L% e. a( D5 E7 G
变量0:
6 x# ^* g8 v& d7 e: R  {0 e0.35 0.62 0.83( \, l) a3 G" e  I2 x: G! l* k! G* F" W
0.20 0.47 0.59  h! S- e6 X4 D
0.25 0.35 0.55
1 Y  A: r* P) h4 _. c变量1:. r( W+ e; R0 o- a, l# N) F
0.92 0.38 0.53 0.57! c  _( N) L$ K
0.29 0.57 0.78 0.47
% l: Q5 G5 w- C0.76 0.08 0.93 0.01& [  D; Q0 k+ ]5 _) d9 }0 d- P0 k
0.75 0.05 0.13 0.34! @, r% }$ Q9 S5 G! b
变量2:* h% {8 E- b+ E* f% G* i
0.16+   0.87j 0.60+   0.43j 0.45+   0.14j 0.83+   0.85j 0.11+   0.08j
; Y1 D, s4 N6 \0.79+   0.08j 0.26+   0.91j 0.08+   0.87j 0.54+   0.62j 0.96+   0.24j) g9 m7 d8 ~) o. M. ]$ n% b
0.31+   0.40j 0.65+   0.18j 0.23+   0.58j 1.00+   0.35j 0.00+   0.12j/ h! I) E( U1 R. M, a& W& w, M5 e
0.53+   0.26j 0.69+   0.26j 0.91+   0.55j 0.08+   0.51j 0.77+   0.18j' _9 p# O' s+ r5 B0 j; F6 @1 z" {
0.17+   0.80j 0.75+   0.15j 0.15+   0.14j 0.44+   0.40j 0.82+   0.24j' a& r: F+ v# I) H+ W
>> help test
, z0 ^- r$ V. V* E3 p- o  P; u本程序用于调试mx______函数.! o* A# |+ g% d( o

! _1 p* K9 G4 a5 Y3 j, M1 `/ O
' \1 Z4 L9 K, `  v) V1 _4 G' g本文来自: 高校自动化网(Www.zdh1909.com) 详细出处参考(转载请保留本链接)http://www.zdh1909.com/html/matlab/14744.html3 l7 O* `3 k' V1 z. @
0 R5 g. I/ F% ?$ y$ S9 X# V
下面是其附件,内容一样,方便下载 Matlab调用c程序.doc (41.5 KB, 下载次数: 10)
作者: 天海星云    时间: 2012-9-1 21:44
很不错的资源
作者: wangtianyang    时间: 2012-9-3 09:25
嗯嗯,很好谢谢楼主
作者: gucci_purple    时间: 2013-1-3 11:17
顶一下。谢谢楼主啊~~
作者: tequila33    时间: 2013-1-8 21:11
很实用啊....谢谢楼主~
作者: lieove    时间: 2013-1-14 23:11
为什么不直接用matlab的m文件写成一个函数得了啊!!!何必这样麻烦呢?
作者: zzllnnhh007    时间: 2013-1-27 19:04
谢谢数学中国的老师们,老师辛苦了
作者: 墨羽飞    时间: 2013-3-1 17:45
谢谢楼主~~~~~~~
作者: fjnanyuan    时间: 2013-4-5 12:25
好高级啊,为什么要10个字符啊
作者: jonejack11    时间: 2013-6-4 00:38
正是我想要了解的,其实编程是相通的,关键是怎么编
作者: pcyaoqiang    时间: 2013-7-12 16:01
支持一下啊!!




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5