数学建模社区-数学中国

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

作者: 梦溪517    时间: 2012-8-28 20:47
标题: Matlab调用c程序

" A2 y2 {$ |/ M! `# YMatlab调用c程序' s% K1 U" M3 n; o
文章来源:不详 作者:佚名 / e/ ]$ O2 \$ V( F  r6 f/ I% A
' e  j* t4 H! R
--------------------------------------------------------------------------------
$ H8 z: t; z: b% i
+ {5 x# H3 d4 T# ^* E9 v3 u1 ?该文章讲述了Matlab调用c程序.
( v% R( g$ P) J" R) M
' d, Q% l4 U5 z5 P3 A方法:
4 v5 t* }  ?0 i, n第一步:要先在matlab中安装c程序编译器,步骤如下:' f7 K5 `9 v( r' y3 t9 b
键入命令:mex -setup
3 o- [6 x' Q* Y1 |2 m选择c/c++编译器;6 [# b0 @, |& c0 s( K7 n' B
选择c/c++编译器版本;. F% b! L3 h4 {  I* j! }' J3 V
确认。) k) Z# D' S1 G2 Y
第二步:键入:mex *.c! [& E( @8 l/ q( C4 A

/ P2 }- F4 b1 S( l, k*********************************************************************************************************************************************
, W, S8 f( H; p* ?( [- l1 u1 b3 i$ r, P' c1 p9 i3 ?* ]
实例介绍:【转】3 j, B% U) m7 L2 J/ M/ R9 E
  B3 {' E2 d9 C$ ~
如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:: e2 g+ U7 R) Z- Z* {: @: U
double add(double x, double y) {
1 J1 F) x- `. o, V9 ` return x + y;6 \" E1 p  O( k( W' {/ Z( K7 T* b
}2 a  R0 r) F9 c! {6 P% J2 q) X: T. j
现在我想要在Matlab中使用它,比如输入:; `+ X3 |# v7 Z9 e; f5 V
>> a = add(1.1, 2.2)& l6 P1 o% U/ q6 H  f2 N4 ^
3.3000
' N% B7 B1 ~3 q7 b& |要得出以上的结果,那应该怎样做呢?. h9 E. s! s( J9 f
解决方法之一是要通过使用MEX文件,MEX文件使得调用C函数和调用Matlab的内置函数一样方便。MEX文件是由原C代码加上MEX文件专用的接口函数后编译而成的。, C* P! v+ U( j1 t! u
可以这样理解,MEX文件实现了一种接口,它把在Matlab中调用函数时输入的自变量通过特定的接口调入了C函数,得出的结果再通过该接口调回Matlab。该特定接口的操作,包含在mexFunction这个函数中,由使用者具体设定。
! ^% u& i3 C; C/ |所以现在我们要写一个包含addmexFunctionC文件,Matlab调用函数,把函数中的自变量(如上例中的1.12.2)传给mexFunction的一个参数,mexFunction把该值传给add,把得出的结果传回给mexFunction的另一个参数,Matlab通过该参数来给出在Matlab语句中调用函数时的输出值(如上例中的a)。" H# G! \; M2 t2 I( U
比如该C文件已写好,名为add.c。那么在Matlab中,输入:; Q3 b8 m" v- ~" P" e9 ^+ Q
>> mex add.c( y( ~- H. D9 y% i3 e
就能把add.c编译为MEX文件(编译器的设置使用指令mex -setup),在Windows中,MEX文件类型为mexw32,即现在我们得出add.mexw32文件。现在,我们就可以像调用M函数那样调用MEX文件,如上面说到的例子。所以,通过MEX文件,使用C函数就和使用M函数是一样的了。
4 [+ P: t* h1 J$ C& R# `我们现在来说mexFunction怎样写。% `2 M" ?# W: f; C+ P% ?% A2 U
mexFunction的定义为:
  u& V( ?% o; w9 L- h. M6 a  W( avoid mexFunction(2 [! y+ f( n) t
     int nlhs,) d0 y/ ~( k" H, b- t
     mxArray *plhs[],
) h3 d1 |3 h+ F2 N/ M( F     int nrhs,( y- J' @) R; w3 g2 b
     const mxArray *prhs[]) {
8 L" x2 t% W% A6 O* ]" f; X$ F% `9 E+ B$ w/ I8 f7 M! L
}
8 S2 ?( [* X1 U! n0 Z0 w' Z8 }可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时:
0 I# K" g0 S+ k7 U+ X4 u3 A+ A; |  F>> b = 1.1; c = 2.2;
# J4 T1 }! Q3 ^% L; J7 g/ z, n/ Z>> a = add(b, c)
: ]! b6 z( q" U, P# S0 kmexFunction四个参数的意思为:" P' |3 }6 B( s
nlhs = 1,说明调用语句左手面(lhsleft hand side)有一个变量,即a
, g) n5 r3 {6 o+ p' Lnrhs = 2,说明调用语句右手面(rhsright hand side)有两个自变量,即bc
$ Q$ z! v2 e$ U7 L: H) Tplhs是一个数组,其内容为指针,该指针指向数据类型mxArray。因为现在左手面只有一个变量,即该数组只有一个指针,plhs[0]指向的结果会赋值给a1 f! d. z' U/ E% N9 A
prhsplhs类似,因为右手面有两个自变量,即该数组有两个指针,prhs[0]指向了bprhs[1]指向了c。要注意prhsconst的指针数组,即不能改变其指向内容。! q$ g! ]5 p2 E; N4 F6 E
因为Matlab最基本的单元为array,无论是什么类型也好,如有double arraycell arraystruct array……所以a,b,c都是arrayb = 1.1便是一个1x1double array。而在C语言中,Matlabarray使用mxArray类型来表示。所以就不难明白为什么plhsprhs都是指向mxArray类型的指针数组。( W0 b8 ]! e# D/ P2 l
完整的add.c如下:0 A! i+ }, r! [4 z) v3 ]+ f7 P% q
// add.c
: |( q& h1 x) Y#include "mex.h" // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数
2 ~  H( m- ]- ^: r; E, Vdouble add(double x, double y) {
* _: ~! l7 P9 q& w+ Y0 p! W return x + y;
; i' J+ M- `- p2 H# Z$ D} // MEX文件接口函数" i# w- A1 b8 e/ h" n) C% d
void mexFunction() c" x; z0 j, F* p9 G
 int nlhs,
9 n3 ]1 V" q% w6 y& ~, v mxArray *plhs[],6 d2 Y* L$ R* ?8 n
 int nrhs,3 r2 o! L% m6 `
 const mxArray *prhs[]) {4 d; L5 M0 ]1 j! r8 }: z
 double *a;0 V, D! }3 U* S5 h  K2 _8 Z7 D
 double b, c;  B6 e4 Y2 q# @9 W' P
 plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);% N( u8 m, _: O6 |- ^7 q6 Q. V# l
 a = mxGetPr(plhs[0]);7 E1 J- o4 p$ x' g
 b = *(mxGetPr(prhs[0]));
% H  n1 o% w* n+ f c = *(mxGetPr(prhs[1]));+ c, l( t& A4 v0 g# h4 L
 *a = add(b, c);1 i3 O+ L: k7 p! |+ |( Q9 }
} 7 Y; A" |# j; J) P) ?  o
mexFunction的内容是什么意思呢?我们知道,如果这样调用函数时:
) S5 D( c4 n8 `! L8 f, u>> output = add(1.1, 2.2);
2 t* x- |( n; X4 y在未涉及具体的计算时,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便是已计算好的结果了。. q; z8 b# g9 H* e  U) M! V
上面说的一大堆指向这指向那,什么mxArray,初学者肯定都会被弄到头晕眼花了。很抱歉,要搞清楚这些乱糟糟的关系,只有多看多练。
' E- w: Z1 @! Y5 ]! b$ U2 k实际上mexFunction是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保0 x( I7 F. B5 Z+ G5 E5 O
输入正确。如在add函数的例子中,用户输入char array便是一种错误了。, p- R2 e; \( W9 e
从上面的讲述中我们总结出,MEX文件实现了一种接口,把C语言中的计算结果适当地返回给Matlab罢了。当我们已经有用C编写的大型程序时,大可不必在Matlab里重写,只写个接口,做成MEX文件就成了。另外,在Matlab程序中的部份计算瓶颈(如循环),可通过MEX文件用C语言实现,以提高计算速度。( D+ h: k3 t6 f/ r: K! r& k% c
/ j+ Y3 B  E/ P+ f' ]
*********************************************************************************************************************************************! H( P' T7 r- u( |# ]) A
% b; E1 K  Y" @6 Z' z4 y+ w/ A
mex 的目的,0 i& v/ b3 e, L7 ^) k! s

0 ^) `: [. b) t$ E通过C/C++语言编写代码,Matlab中将其编译成mex文件主要可以做以下几方面的事情:
& F/ B# c! A4 Y6 f! E3 y6 F# u! Z0 J: W
1、加快程序的执行速度. Matlabfor上如老牛拉车的速度确实让人抓狂.
' ?6 N9 `% R8 A+ h- d
# o; _* ^, w+ Q6 q. x6 ]2、将Matlab作为C++的开发调试环境.尤其是有大量数据需要处理时,Matlab观察其中间结果十分方便.
, ~# K3 Y6 j2 o3 X" T! k4 f) V9 a5 x- a9 _% D! ?  v
3、据称可以弥补Matlab硬件设备接口的薄弱环节.8 `) V9 T6 A; Y& S# E

9 K1 i1 s( h& Z9 @4 H/ k' S! p今天写了第一个使用MEX.5 w3 b3 W: N  V4 ]% h8 J% B+ M+ C

: n0 k! C0 T6 ]3 v; C一个简单的对Matlab普通数值矩阵的操作.* P, r3 C' n" H1 x* O; _* E7 L

" M9 q1 ]9 H5 a$ D# l其中Matlab规定的与操作系统版本有关的mwSize,mwIndex, size_t32位系统上其实本质上就是int,所以
7 ]7 I, s/ `- Y% b1 V; j! k# s
9 U9 L' v' V: j一律用int代替.
) J) l1 E) M+ w7 J7 O+ `
( V+ _: o" `6 R" w7 P& q#include "mex.h"
! E; G. B4 h1 Q1 A8 W2 H6 X#include <iostream>
) ~' J8 m3 m% ?+ p  l4 f2 G. F* }0 D/ N# u" `6 v
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
+ ^, i" r4 g! h5 o2 [' d" J{
) I" r$ y* A. O0 `6 y. a, r; \9 e5 K- p! W4 _2 k7 U
int i,j,k;
1 ~% g0 Z( E4 b) B3 |$ wint index;, C6 b8 P6 ?/ u* ~4 R; [; k
double* pr=NULL;* {( M, T0 \+ S+ F  J
double* pi=NULL;" v3 w) v5 I8 _* Z9 m1 Z
int M,N;. F8 ^2 k9 c, m# |/ g% X: Z- ]5 Q( }% S
int ndim;7 r- T/ j  B( h2 O# ^
int dims[2];: P2 q$ c/ D  u' }5 ]
for (i=0;i<nrhs;i++)% C$ k7 D& T6 ?
{  T! }9 H4 b1 N& H& W# }
   if ((mxIsDouble(prhs))&&(mxGetNumberOfDimensions(prhs)==2))
) u4 T$ Z" e4 V8 I5 r( \' i4 S* K( g   {8 U) l; E+ F: z6 i6 E3 |1 ?
    pr=mxGetPr(prhs);6 J! ?* x- v1 g" `/ v
    pi=mxGetPi(prhs);- F, O3 d5 T9 S- M
    M=mxGetM(prhs);  m5 q7 B" V5 N. I5 z
    N=mxGetN(prhs);* H0 |3 T, M4 G2 G$ O# ^' N' u' t
    ndim=mxGetNumberOfDimensions(prhs);
# m, q' i: |- c9 O( p5 X8 G% e6 U+ f0 J$ p, k
    mexPrintf("变量%d:\n",i);
  \0 T& L0 V9 M2 J( `* D    for (j=0;j<M;j++)
6 {3 {8 R& S0 s: t; o6 H: r    {
9 y* R1 t% q) M5 O% r6 l, M     dims[0]=j;, q) D3 _0 R% e% s
     for (k=0;k<N;k++)
' f4 E# {. n% H: i! S/ k     {' h/ i9 m1 ^# J
      dims[1]=k;7 d- D. W* K1 e* u
      index=mxCalcSingleSubscript(prhs,ndim,dims);4 Y8 o/ }5 M! t" h( M/ l0 ~8 n3 [
      if (pi==NULL)
& x( S/ c* v. A9 V      {
4 j3 d2 F0 v* R9 ?0 t* C* B       mexPrintf("%6.2f",pr[index]);
4 C, l; n/ b7 r1 n# a      }
' d& h5 G0 o; h  H$ s      else{& Y- T: w! D$ a
       mexPrintf("%6.2f+ %6.2fj",pr[index],pi[index]);
' a% F" a0 w# O  S+ t  z7 E7 ^. n9 p      }; N& l! Q) M, v* Z3 e
     }4 A3 R  V5 K  ?! ~
     mexPrintf("\n");
8 D5 G* l& p2 B0 v) p1 `4 n# G( m& r" i- a/ Z' G3 W
    }
1 V- e# f5 r# D. }# l, a  
$ X) T/ @8 _* m2 X   }* v7 Q4 L; b% u3 V0 G, u. {9 C) P
   else{
8 X5 T& U+ s6 N+ S) M% F  l+ z    mexPrintf("input NUMB %d matrix is not 2 dims&double numerical array\n",i);
- L: A7 B' x& }1 ^: f}
% K2 `0 l  p, x- a+ ?" E, X  u$ X( R, \
# C) K, {6 B% G3 ]. Q3 D* \% F9 X
}7 y5 [& q7 V* D; o5 W9 i
4 b8 x# J& g9 g) x% K# x6 c
}4 _. f: b0 b9 o
# w9 N  O- w% G0 \: U3 q
Result:% O% f- S6 O; l! ^
( n8 n# b8 T0 N: k1 ?+ z* _
>>mex test.cpp
, D2 u; M% a. R* p; V>> test(a,b,c)( a3 P  u' g# p% c. S
变量0:
. q+ Z! |/ x$ J4 t1 n+ e5 F9 N0.35 0.62 0.83
" t$ d! ?: f% }6 d/ \0.20 0.47 0.59
$ A$ I; T5 R6 m1 _1 f. y* e$ D, E0.25 0.35 0.55
: F+ s# L0 i, u! P* F; u6 Y/ Y2 [) z变量1:
0 g) ?  o' e+ g7 i& W0 ]0.92 0.38 0.53 0.57
6 ^& P, K' V+ S( @3 t0.29 0.57 0.78 0.47$ {1 Y8 F5 j$ T0 u. k  Y
0.76 0.08 0.93 0.014 [* M3 J  ]8 s8 J' F9 ?
0.75 0.05 0.13 0.34- @/ j9 \* @+ ?/ q! \7 w8 B. c
变量2:
( Q: K$ m' }; w. Z; |0.16+   0.87j 0.60+   0.43j 0.45+   0.14j 0.83+   0.85j 0.11+   0.08j, z: q0 N* S# R$ b; M9 I. M
0.79+   0.08j 0.26+   0.91j 0.08+   0.87j 0.54+   0.62j 0.96+   0.24j
2 t' q2 u5 V- x! d7 K1 |0.31+   0.40j 0.65+   0.18j 0.23+   0.58j 1.00+   0.35j 0.00+   0.12j
2 ~0 J' \" E0 x3 H% I0 K0.53+   0.26j 0.69+   0.26j 0.91+   0.55j 0.08+   0.51j 0.77+   0.18j
* a# Z6 u, v" T( j0 E6 Z3 |0.17+   0.80j 0.75+   0.15j 0.15+   0.14j 0.44+   0.40j 0.82+   0.24j. O( ~( z, }% a% `. w
>> help test
! x5 n6 L) \$ p本程序用于调试mx______函数.1 p- r. ?; Y6 h! j/ K

9 w, ^" {) J- r% j# ~2 _1 z5 U2 i. ~
本文来自: 高校自动化网(Www.zdh1909.com) 详细出处参考(转载请保留本链接)http://www.zdh1909.com/html/matlab/14744.html
4 w4 A$ K5 E6 s5 S  a6 ^- O5 u1 b) o, p5 C' e4 m1 m  |
下面是其附件,内容一样,方便下载 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