数学建模社区-数学中国

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

作者: 梦溪517    时间: 2012-8-28 20:47
标题: Matlab调用c程序
1 h9 j. D6 A) x4 P
Matlab调用c程序) k7 }9 _, d1 y' V: Q4 G( ^
文章来源:不详 作者:佚名
' {! f" l; K- q  x& r, W
9 [3 L* K: \1 l  g! Y# U--------------------------------------------------------------------------------! N5 u  b: M& F1 \
4 o. J, e0 [& ^0 T3 d3 {
该文章讲述了Matlab调用c程序.# Q' L1 R; u: e! J5 v5 t% i# {

" G. z- g) Q' {方法:; {$ M5 c3 ^$ n  I. @' \
第一步:要先在matlab中安装c程序编译器,步骤如下:, C* o  _$ \1 Y5 z1 M; @
键入命令:mex -setup
% m9 L/ c) J$ t! R" N6 q$ c6 |选择c/c++编译器;% l& ]8 i" q9 k! }
选择c/c++编译器版本;
& l5 D2 m  O6 P$ V8 t% V. D6 x' \确认。
! ]. {+ R/ C1 y% T6 h第二步:键入:mex *.c7 L2 s7 r; S# _( O

  R( ^, `# `9 E( ]+ Q& W*********************************************************************************************************************************************) Q- ]& R3 D: z  |* a

* y5 w: Z& w" w/ e7 S7 y实例介绍:【转】
: a+ @# \" s9 U
: M9 ^' c; A! r9 o) |如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:
+ N, e* s* D  tdouble add(double x, double y) {& A8 ~; n9 s# K1 _& F" F
 return x + y;
: y3 H# ^: v0 O7 h}1 Y# u( [$ `+ _
现在我想要在Matlab中使用它,比如输入:
; N5 w" i, b; d& M>> a = add(1.1, 2.2)$ g9 H4 H& w4 g2 o1 n0 g# `
3.3000
8 i5 i4 n2 k' \, I6 z- a% t; O/ i要得出以上的结果,那应该怎样做呢?' l6 r" X5 R, J* H# S( c9 l$ r
解决方法之一是要通过使用MEX文件,MEX文件使得调用C函数和调用Matlab的内置函数一样方便。MEX文件是由原C代码加上MEX文件专用的接口函数后编译而成的。8 C# r6 D) ~% a% w8 k( Z1 V) N9 ?+ f
可以这样理解,MEX文件实现了一种接口,它把在Matlab中调用函数时输入的自变量通过特定的接口调入了C函数,得出的结果再通过该接口调回Matlab。该特定接口的操作,包含在mexFunction这个函数中,由使用者具体设定。
/ [! i4 R( ]. {9 v4 ^. p2 H" T所以现在我们要写一个包含addmexFunctionC文件,Matlab调用函数,把函数中的自变量(如上例中的1.12.2)传给mexFunction的一个参数,mexFunction把该值传给add,把得出的结果传回给mexFunction的另一个参数,Matlab通过该参数来给出在Matlab语句中调用函数时的输出值(如上例中的a)。6 k& {; l- G: H1 q4 s2 Y
比如该C文件已写好,名为add.c。那么在Matlab中,输入:& h& l; Z' ?( k* I4 ^; U5 n
>> mex add.c. S3 N7 n; c; H
就能把add.c编译为MEX文件(编译器的设置使用指令mex -setup),在Windows中,MEX文件类型为mexw32,即现在我们得出add.mexw32文件。现在,我们就可以像调用M函数那样调用MEX文件,如上面说到的例子。所以,通过MEX文件,使用C函数就和使用M函数是一样的了。
) z. N. r* }8 z( b: u5 b1 T& \我们现在来说mexFunction怎样写。
* v# S5 J4 T8 e! BmexFunction的定义为:' G+ n  T2 A' t; a3 y7 Q/ Y5 Z
void mexFunction(# p/ k1 C  l: ]! `: P7 Y; p
     int nlhs,
: x& j. U$ T( D) X: ~7 Y$ n     mxArray *plhs[],
0 H4 N! G+ ?, K- T$ R) I5 c( P     int nrhs,6 w; F' [" X6 p0 o( ]
     const mxArray *prhs[]) {
" ]; m3 |0 X! v& V+ o1 o: B, O6 x+ T( L1 G9 a, P7 s
}
) c, @9 S) r+ \! u6 }9 Y3 U  r2 v5 g+ a可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时:
+ A. V0 I1 {: h; w>> b = 1.1; c = 2.2;7 A! b& ?# f6 g# _3 p
>> a = add(b, c)/ F* [/ X, g2 f
mexFunction四个参数的意思为:
# U' I- D3 s0 i' Z. h# Hnlhs = 1,说明调用语句左手面(lhsleft hand side)有一个变量,即a
0 _9 R9 q( ]) i% W1 unrhs = 2,说明调用语句右手面(rhsright hand side)有两个自变量,即bc( K3 X( n  L1 y, G
plhs是一个数组,其内容为指针,该指针指向数据类型mxArray。因为现在左手面只有一个变量,即该数组只有一个指针,plhs[0]指向的结果会赋值给a" A! Q5 E% R' L! _3 [' S% r
prhsplhs类似,因为右手面有两个自变量,即该数组有两个指针,prhs[0]指向了bprhs[1]指向了c。要注意prhsconst的指针数组,即不能改变其指向内容。
9 m" B: ?+ ]0 l因为Matlab最基本的单元为array,无论是什么类型也好,如有double arraycell arraystruct array……所以a,b,c都是arrayb = 1.1便是一个1x1double array。而在C语言中,Matlabarray使用mxArray类型来表示。所以就不难明白为什么plhsprhs都是指向mxArray类型的指针数组。' }+ y/ q, v% o/ N3 x1 e! I) K
完整的add.c如下:& c1 F5 a( r2 ^
// add.c
# w. Q) Z! e" G7 |- o#include "mex.h" // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数+ E3 D4 I: D* q, Q# r
double add(double x, double y) {( u+ [* l8 j8 [
 return x + y;
$ A$ V2 I/ Q+ ?} // MEX文件接口函数
8 u/ g# X( c) G/ w7 `4 F  I0 ^void mexFunction(0 ^. z. s" l! Z! I
 int nlhs,! J& A6 y! V) q3 t
 mxArray *plhs[],) D7 c( P5 j  {% j4 e5 N
 int nrhs,( W2 `" G, }( q, S8 l
 const mxArray *prhs[]) {
9 o3 A( q/ @/ i; j0 f& y% Z double *a;9 g  d. w+ J) \5 ?  Z' u
 double b, c;
7 H; ~  w8 l2 c1 j5 ?! [ plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);; p; g& r" _' S" e1 u6 R
 a = mxGetPr(plhs[0]);7 g0 ~$ D" q, n$ E
 b = *(mxGetPr(prhs[0]));
* `6 Z& L% G$ ]; i! G; I! c c = *(mxGetPr(prhs[1]));$ d9 j  D1 u2 Q; h
 *a = add(b, c);
! `" [9 J/ E" T0 Z" ?}
* ]- L9 n" s0 ZmexFunction的内容是什么意思呢?我们知道,如果这样调用函数时:; u; D% k& a% `9 m. B
>> output = add(1.1, 2.2);$ X' f& Z, ~% `4 l
在未涉及具体的计算时,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便是已计算好的结果了。
+ I- n( l5 p( Y上面说的一大堆指向这指向那,什么mxArray,初学者肯定都会被弄到头晕眼花了。很抱歉,要搞清楚这些乱糟糟的关系,只有多看多练。* A- ^$ C7 e8 d. f
实际上mexFunction是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保- L3 F1 u0 p0 F& i5 s: ~
输入正确。如在add函数的例子中,用户输入char array便是一种错误了。& {5 U& y4 Q+ G
从上面的讲述中我们总结出,MEX文件实现了一种接口,把C语言中的计算结果适当地返回给Matlab罢了。当我们已经有用C编写的大型程序时,大可不必在Matlab里重写,只写个接口,做成MEX文件就成了。另外,在Matlab程序中的部份计算瓶颈(如循环),可通过MEX文件用C语言实现,以提高计算速度。
' r  [! B8 _) ?" u
. q8 X) E2 f; ?  N, h( |*********************************************************************************************************************************************
$ Q. j. s, L0 E! |) B% x8 {1 u9 F& L0 R5 T% g
mex 的目的,
$ h/ {# q1 W& ~* `) I5 Y7 G8 Z+ [4 V1 D
通过C/C++语言编写代码,Matlab中将其编译成mex文件主要可以做以下几方面的事情:& \0 x0 T( ^/ E/ o' x8 r9 g

9 a& _8 R4 W6 H$ t# j( }7 }1、加快程序的执行速度. Matlabfor上如老牛拉车的速度确实让人抓狂.
, E; X- d7 E/ N' s7 J7 T5 r( _6 Y
+ l9 M- Q# P- m( M7 y% k. f1 D2、将Matlab作为C++的开发调试环境.尤其是有大量数据需要处理时,Matlab观察其中间结果十分方便.& ^& R; M) J& I5 |

0 M  E' u4 d4 f: B& l3、据称可以弥补Matlab硬件设备接口的薄弱环节.
3 B  G: _  k. W8 Z: x( X  q& {& `( \, e1 q) F
今天写了第一个使用MEX.
/ \( b) B* R+ c4 _4 U7 i
- V! `& X1 r/ T一个简单的对Matlab普通数值矩阵的操作.$ A( u' v* V9 b% Q7 ^

: e$ y3 i2 |; ]3 V其中Matlab规定的与操作系统版本有关的mwSize,mwIndex, size_t32位系统上其实本质上就是int,所以1 w( V* {% B" v2 r" L

* Y* x: q& {; \一律用int代替.
4 D4 G$ [5 r6 L( R: l* X
# r4 g2 {- I0 C7 z, w4 h#include "mex.h"
0 \8 ^3 O% v" K" s1 b#include <iostream>& O! `+ i: f& P9 _0 S9 V  G
  ]2 S9 F! Z7 f
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])% V# {2 V' o6 z& e/ r4 s" \: i0 g
{
) K: v' E& a) t+ n5 |, Y5 c. t! r( q: V4 @3 z
int i,j,k;3 x# p) X1 E  K3 W
int index;- J. C* w7 u6 S5 F/ e& l, o2 P
double* pr=NULL;
! f2 H5 }; r4 hdouble* pi=NULL;5 L2 A, p/ q6 M* c# L
int M,N;
+ B% G+ M- P. K6 x" _. gint ndim;
* s: a# s: s) j) S5 T9 u- d' Rint dims[2];" s7 m' ~: O) L% f5 Y" |. U5 G  H5 ?+ \
for (i=0;i<nrhs;i++)% C1 V* g0 e! |" b
{
( _4 Y) Y/ Z6 S. z: F   if ((mxIsDouble(prhs))&&(mxGetNumberOfDimensions(prhs)==2)), E5 u+ L9 n+ w6 y. J' @
   {
. L3 Q7 X: [, H5 h! \' }3 N    pr=mxGetPr(prhs);  Z' M* }1 y1 o
    pi=mxGetPi(prhs);" _5 ~( P$ ]5 I% Q" |$ Q
    M=mxGetM(prhs);- L" a6 P; `4 H* R3 N
    N=mxGetN(prhs);
0 y' k7 q3 y' z2 J; H    ndim=mxGetNumberOfDimensions(prhs);3 X' J% U6 l, `4 J

! J; }% D, @- \: O/ ?    mexPrintf("变量%d:\n",i);4 n7 X( O0 T3 w. h; J3 A
    for (j=0;j<M;j++)
) H$ x1 U8 `! e! B5 C/ D    {
* h+ q3 L2 V+ ]     dims[0]=j;) ]+ |; B7 ], C! K* h
     for (k=0;k<N;k++)
/ ^4 \% P' }) l     {, f" s2 h* @/ k; S# O+ d
      dims[1]=k;. z2 [9 M# @0 }7 ^* o0 k
      index=mxCalcSingleSubscript(prhs,ndim,dims);: i, o# z% n& M* S3 q% c7 l
      if (pi==NULL)1 Z' {7 F& @% {4 ~; j4 {# {* r
      {6 e! |5 n  L  D5 Y  ?3 v  c
       mexPrintf("%6.2f",pr[index]);
0 N9 G9 k4 L+ G# o% V% S+ b9 U      }& R& k6 B; n8 ^$ z- G/ X7 S
      else{
+ B- L9 b& ~) E( i       mexPrintf("%6.2f+ %6.2fj",pr[index],pi[index]);
- k3 }, v% ?% g; B% e      }
! g0 E# A& J( r  c) Q( y     }
0 X( |  l5 M; X& d% m     mexPrintf("\n");
) D) I7 w9 V0 M8 |7 ]8 |+ T6 j
. G. X5 `6 [9 @1 ~9 C5 l( o    }
2 c4 M5 J# O$ k. n3 w  
* U0 ^$ p5 p& ^- ?1 E  y   }3 f. q5 {* e% _
   else{
* D( v% M% H2 Z8 ^& h    mexPrintf("input NUMB %d matrix is not 2 dims&double numerical array\n",i);
! U+ f5 P8 e" v* u9 j}8 F0 G$ k4 B7 ^0 f* z! I- M
, D3 M, ?" |9 e$ p* k* T
* [6 A/ }9 d0 ?* ~: `) O' \$ \
}' s, k) Z2 z. C. R0 n6 ]
! e$ t/ A7 h& \) ~1 @* k& B8 I
}
3 W: K! I7 s5 g/ z$ o/ @8 k* P% S  T# j. E4 i
Result:2 Y6 w4 p4 l, L& f/ {, j# s

+ b  I4 r6 r: a. q- j- p8 d>>mex test.cpp3 g; G* K2 }8 N0 V" ]
>> test(a,b,c): |9 i3 S$ ]/ }5 H' L8 W
变量0:6 q  U$ U2 c( |9 B; a
0.35 0.62 0.83
# R3 o7 p$ A3 ~, i+ ~: m: d! y0.20 0.47 0.59
8 m1 F1 W/ B6 M3 e+ z4 q% R' W0.25 0.35 0.55
) T. _& }; H8 J" v9 ]变量1:, ~% W6 q1 [! z5 K6 ?3 n7 L7 S
0.92 0.38 0.53 0.57
7 j) t* X" l( V# q$ c. R5 u, Q. I6 z0.29 0.57 0.78 0.47
/ R! Z' L6 \  A3 g+ C. g0.76 0.08 0.93 0.015 `  E: S3 Q0 u/ B, E& V
0.75 0.05 0.13 0.34) f1 c0 S2 s5 O- E
变量2:1 ?4 B% K( J, d! Z& l/ V
0.16+   0.87j 0.60+   0.43j 0.45+   0.14j 0.83+   0.85j 0.11+   0.08j
. G  H2 Z9 {! O6 t9 O: z0.79+   0.08j 0.26+   0.91j 0.08+   0.87j 0.54+   0.62j 0.96+   0.24j- I$ }2 V' W; P9 M- ^) q
0.31+   0.40j 0.65+   0.18j 0.23+   0.58j 1.00+   0.35j 0.00+   0.12j8 Y' Y. t7 ^" g  D: q
0.53+   0.26j 0.69+   0.26j 0.91+   0.55j 0.08+   0.51j 0.77+   0.18j
% [6 i: x: b" {0.17+   0.80j 0.75+   0.15j 0.15+   0.14j 0.44+   0.40j 0.82+   0.24j) C6 l0 N2 }! J. ?# O" W; m; c0 q6 R
>> help test8 ~% p& C" x+ t) i+ q; t
本程序用于调试mx______函数." t# x' y4 R% x& a1 J
- Y: Y1 V; r7 F) t. f
/ h  T) v9 i: B, \
本文来自: 高校自动化网(Www.zdh1909.com) 详细出处参考(转载请保留本链接)http://www.zdh1909.com/html/matlab/14744.html
8 G* n/ x3 m# y1 j! I. H% [/ \: z9 q' r( ~& a' t) ~  }
下面是其附件,内容一样,方便下载 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