在线时间 51 小时 最后登录 2014-2-12 注册时间 2012-3-10 听众数 5 收听数 0 能力 0 分 体力 592 点 威望 0 点 阅读权限 30 积分 230 相册 0 日志 0 记录 3 帖子 101 主题 18 精华 0 分享 0 好友 18
升级 65%
TA的每日心情 开心 2014-2-12 10:47
签到天数: 52 天
[LV.5]常住居民I
群组 : Matlab讨论组
群组 : C 语言讨论组
群组 : 学术交流B
群组 : 学术交流A
群组 : 2013年数学建模国赛备
$ G2 O3 d5 T, c5 m7 C' z' s! \0 ^
Matlab调用 c 程序 ) C: F: Z0 @7 b% ?6 Z. o
文章来源:不详 作者:佚名 $ J: }; J# W( w5 M1 Y; v$ q
' R. ?! Y: @! ~" s7 ^ -------------------------------------------------------------------------------- 3 D, {! F) x% k: P" u
) b* E6 Q4 N, z 该文章讲述了Matlab 调用 c 程序 .
* x% G- i4 W2 ~) j1 L& P
' H0 p j9 z3 A! }$ t, t 方法: 1 y1 R/ ^8 n- A; p1 a! C
第一步:要先在matlab 中安装 c 程序编译器,步骤如下:
2 S2 G" X% N7 J( T' ?, k0 H- o6 R { 键入命令:mex -setup ;
' V& w4 q1 n1 `; P0 m: j9 c. l" c) I: w8 z 选择c/c++ 编译器;
6 y' r# Q* Z0 w6 [' P- ]# ]' O; s 选择c/c++ 编译器版本; / |) g! o: G) ~! e9 R
确认。
. D |* [+ o7 h 第二步:键入:mex *.c , }6 f T, C+ b9 ?" ?# e1 m$ _$ ~
! T* f7 p$ W% y" F( l4 x
********************************************************************************************************************************************* - c. ]# v3 {9 V- P* f
- b& m1 x; y% m* W 实例介绍:【转】 9 x: R6 J$ C& E. q
2 e& ]; N4 \, j: } 如果我有一个用C 语言写的函数,实现了一个功能,如一个简单的函数: : y, ^1 g" l! n d4 m5 e8 I) U- n
double add(double x, double y) { 7 `3 w# U1 T) j
return x + y;
5 ?: \' t% C7 l7 R8 V } & W. f9 q# E/ H( S6 ~, {4 q; a* }# K
现在我想要在Matlab 中使用它,比如输入:
7 |! x+ z9 C' J: X" u >> a = add(1.1, 2.2) ' o0 b( r7 C: b
3.3000
8 Y1 U0 k& Y" w, i6 f8 P' v 要得出以上的结果,那应该怎样做呢?
0 `9 t) y+ j8 v; H6 R: k 解决方法之一是要通过使用MEX 文件, MEX 文件使得调用 C 函数和调用 Matlab 的内置函数一样方便。 MEX 文件是由原 C 代码加上 MEX 文件专用的接口函数后编译而成的。
$ }2 V x8 K6 h 可以这样理解,MEX 文件实现了一种接口,它把在 Matlab 中调用函数时输入的自变量通过特定的接口调入了 C 函数,得出的结果再通过该接口调回 Matlab 。该特定接口的操作,包含在 mexFunction 这个函数中,由使用者具体设定。 4 G! k. |% q: s+ ]0 x
所以现在我们要写一个包含add 和 mexFunction 的 C 文件, Matlab 调用函数,把函数中的自变量(如上例中的 1.1 和 2.2 )传给 mexFunction 的一个参数, mexFunction 把该值传给 add ,把得出的结果传回给 mexFunction 的另一个参数, Matlab 通过该参数来给出在 Matlab 语句中调用函数时的输出值(如上例中的 a )。
& ]$ s: q! T. X. D 比如该C 文件已写好,名为 add.c 。那么在 Matlab 中,输入:
8 h. @9 n1 Y& | >> mex add.c # }4 d# t9 G* |4 S9 A, L, B
就能把add.c 编译为 MEX 文件(编译器的设置使用指令 mex -setup ),在 Windows 中, MEX 文件类型为 mexw32 ,即现在我们得出 add.mexw32 文件。现在,我们就可以像调用 M 函数那样调用 MEX 文件,如上面说到的例子。所以,通过 MEX 文件,使用 C 函数就和使用 M 函数是一样的了。 + ]/ A0 g3 A9 ~
我们现在来说mexFunction 怎样写。 * ]2 z4 j( p5 D3 g
mexFunction的定义为: 2 g4 R$ d1 d8 F) e7 y" L% _
void mexFunction(
$ g5 h9 T9 R2 _; u8 m1 |6 D* Q1 m int nlhs,
3 d9 \+ Q0 G, W5 E6 U% q+ } mxArray *plhs[], & d+ j% B( ] j. o; o
int nrhs,
7 e! ]+ ~7 {! r% |6 N const mxArray *prhs[]) {
" e' s$ ?4 h& U) p4 o/ f E1 E0 x8 M6 Y$ f$ }# x
}
: R# x$ s& z+ u% P7 E1 X, K 可以看到,mexFunction 是没返回值的,它不是通过返回值把结果传回 Matlab 的,而是通过对参数 plhs 的赋值。 mexFunction 的四个参数皆是说明 Matlab 调用 MEX 文件时的具体信息,如这样调用函数时: $ U0 k. m' b* I& J6 M
>> b = 1.1; c = 2.2; $ |7 p# L3 C8 I1 L
>> a = add(b, c) 3 y) D+ A! |3 t' p
mexFunction四个参数的意思为: / ^0 [+ Y6 c" R2 y, i3 e
nlhs = 1,说明调用语句左手面( lhs - left hand side )有一个变量,即 a 。
5 H: [& W; M l" y5 D& ~ nrhs = 2,说明调用语句右手面( rhs - right hand side )有两个自变量,即 b 和 c 。
/ |8 e" m( N4 H6 }2 y. V plhs是一个数组,其内容为指针,该指针指向数据类型 mxArray 。因为现在左手面只有一个变量,即该数组只有一个指针, plhs[0] 指向的结果会赋值给 a 。
- t; t; G: K& V ] c! ~ prhs和 plhs 类似,因为右手面有两个自变量,即该数组有两个指针, prhs[0] 指向了 b , prhs[1] 指向了 c 。要注意 prhs 是 const 的指针数组,即不能改变其指向内容。 , O/ z' t8 N* C: Q7 m
因为Matlab 最基本的单元为 array ,无论是什么类型也好,如有 double array 、 cell array 、 struct array ……所以 a,b,c 都是 array , b = 1.1 便是一个 1x1 的 double array 。而在 C 语言中, Matlab 的 array 使用 mxArray 类型来表示。所以就不难明白为什么 plhs 和 prhs 都是指向 mxArray 类型的指针数组。
+ _* R3 Q* [& b& T# p 完整的add.c 如下:
, A4 |- p+ M( j7 H) I. [" g // add.c
2 u. L$ ^6 U5 T. p' N5 d& T #include "mex.h" // 使用 MEX 文件必须包含的头文件 // 执行具体工作的 C 函数
- U8 U9 { M {1 Y" k double add(double x, double y) { 3 |! ?5 O1 ~% m2 L7 ]+ {
return x + y; * M$ K1 k9 G+ O2 r+ { w+ E7 t
} // MEX文件接口函数 2 t: Z; F3 a3 R4 V( H& ^
void mexFunction(
# I9 `# i, Q8 U) T int nlhs, ( F6 c( x+ `7 E8 Y
mxArray *plhs[], : @& d0 n. h- b/ b. W: c6 E
int nrhs, . _- G1 G2 N. Y5 {7 j
const mxArray *prhs[]) { ) m, b# [% D7 |; y
double *a; - @# P! m! c. r+ ^! P) L. b
double b, c; 6 K' _1 i. g& J9 @" T g
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); / ~6 }: u" B9 P' |
a = mxGetPr(plhs[0]);
( L( }6 v3 s# P k7 Y: m b = *(mxGetPr(prhs[0])); % \* z) m- A1 }% Z
c = *(mxGetPr(prhs[1])); / s" s, a5 X" B4 a2 V
*a = add(b, c);
; p. q, E& y S8 P# k% F }
' E6 D/ E& F/ j4 n8 ? mexFunction的内容是什么意思呢?我们知道,如果这样调用函数时:
% W- v Z$ c/ q5 w: m0 r! ~ ?$ } >> output = add(1.1, 2.2); ( U1 N$ ^: X2 u3 p! z6 v
在未涉及具体的计算时,output 的值是未知的,是未赋值的。所以在具体的程序中,我们建立一个 1x1 的实 double 矩阵(使用 mxCreateDoubleMatrix 函数,其返回指向刚建立的 mxArray 的指针),然后令 plhs[0] 指向它。接着令指针 a 指向 plhs[0] 所指向的 mxArray 的第一个元素(使用 mxGetPr 函数,返回指向 mxArray 的首元素的指针)。同样地,我们把 prhs[0] 和 prhs[1] 所指向的元素(即 1.1 和 2.2 )取出来赋给 b 和 c 。于是我们可以把 b 和 c 作自变量传给函数 add ,得出给果赋给指针 a 所指向的 mxArray 中的元素。因为 a 是指向 plhs[0] 所指向的 mxArray 的元素,所以最后作输出时, plhs[0] 所指向的 mxArray 赋值给 output ,则 output 便是已计算好的结果了。
$ e1 e W: x/ g$ g$ Y 上面说的一大堆指向这指向那,什么mxArray ,初学者肯定都会被弄到头晕眼花了。很抱歉,要搞清楚这些乱糟糟的关系,只有多看多练。
) J9 i/ V. I4 {' W c6 t# \& @ 实际上mexFunction 是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保 $ W% }* F9 R5 T: A0 x; i( f
输入正确。如在add 函数的例子中,用户输入 char array 便是一种错误了。
% c A% f# d P2 n) X 从上面的讲述中我们总结出,MEX 文件实现了一种接口,把 C 语言中的计算结果适当地返回给 Matlab 罢了。当我们已经有用 C 编写的大型程序时,大可不必在 Matlab 里重写,只写个接口,做成 MEX 文件就成了。另外,在 Matlab 程序中的部份计算瓶颈(如循环),可通过 MEX 文件用 C 语言实现,以提高计算速度。 # u5 N# X4 F% C
: u) c, M) N- H, j( j ********************************************************************************************************************************************* ) U# |/ z6 L0 U# E" k* p
% x& S5 G9 N; F: }5 c) Y mex 的目的 ,
2 ^( I+ x6 [+ \( d8 t V8 S
" t9 l' I1 ~3 q6 [; J' k# i 通过C/C++ 语言编写代码 , 在 Matlab 中将其编译成 mex 文件主要可以做以下几方面的事情: $ k3 {/ p0 d$ t! ^
& E# v5 D9 m# b; z
1、加快程序的执行速度 . Matlab 在 for 上如老牛拉车的速度确实让人抓狂 . 2 x/ Y% p0 m/ P3 V
$ v- R5 J; D. ~6 y" ]( |
2、将 Matlab 作为 C++ 的开发调试环境 . 尤其是有大量数据需要处理时 , 用 Matlab 观察其中间结果十分方便 . 5 Y/ l% q; F; M1 E1 X
- T( p2 B, ]. p* q/ {
3、据称可以弥补 Matlab 硬件设备接口的薄弱环节 . 6 k% { {; E/ U _
/ }; t- o0 n" N1 @, U& x) ?- H* y3 } 今天写了第一个使用MEX. . p C( [% m9 `% q) O9 r
& \$ C, D8 `+ d5 Z 一个简单的对Matlab 普通数值矩阵的操作 . 2 q) b1 T1 g/ u& _5 F' C
6 |9 Y( C; ]* O% c4 \# H% z
其中Matlab 规定的与操作系统版本有关的 mwSize,mwIndex, size_t 在 32 位系统上其实本质上就是 int, 所以 * w5 I% V4 e f. z8 P
. I: C& A/ K. S1 m% q 一律用int 代替 . - {% q4 }7 }; O+ @+ l3 e F$ Z9 Z9 R3 J0 d& Q
% t5 G" m4 c) j/ R* k
#include "mex.h"
/ h- R3 j5 y) o: ?% C$ D #include <iostream> 4 J2 |1 M; c. n: y3 ^/ H( W0 r8 b
: g. p8 |8 ~: l# ^- _ void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) % T% W* g. W0 e. M# u, |7 Y
{ . b' C* ~( b, \6 c1 K0 }
" N z( L& c4 @% d$ l3 f( w
int i,j,k;
7 w* A* r% ~$ W& q. F! _4 ? int index; ; I- S8 y( l4 }# s0 i. g$ q5 o/ N
double* pr=NULL; , d1 o. n5 f* _+ Q* k+ g0 M; \
double* pi=NULL;
5 `1 m7 c' @; L8 g0 @& N int M,N; 8 a/ `( i+ `0 l2 K& L+ d; {4 B2 l7 Z
int ndim; 9 d3 L; b% D% ~5 f% z
int dims[2]; . P! {1 c$ F- c, I+ t! H. U
for (i=0;i<nrhs;i++)
; ]7 f4 h# j3 L2 E. j, i$ c& B {
( t( I1 P. `; O: t% }6 F9 b% G, B if ((mxIsDouble(prhs))&&(mxGetNumberOfDimensions(prhs)==2))
) E. T8 t G8 p6 S8 Q { : c6 O5 l- t4 C
pr=mxGetPr(prhs); . A& K$ V7 A3 Z: F- U" J* \
pi=mxGetPi(prhs);
% \2 d7 q, z8 Z6 e" _4 { M=mxGetM(prhs); % c5 h. |9 v8 Q3 ~: P
N=mxGetN(prhs);
) U; `! w6 N T9 y* h! E ndim=mxGetNumberOfDimensions(prhs);
; ?$ Z- y& B8 h. S ; Q! t' ^5 J( J7 G
mexPrintf("变量 %d:\n",i); 3 B$ B1 y# z* S8 c& x6 e
for (j=0;j<M;j++)
4 c- [2 A- o. i: P0 y2 s0 q" H! Q) t7 b { 8 K6 A% w8 A. L" z# F7 k
dims[0]=j; @- v: e# t: F) {
for (k=0;k<N;k++)
/ S6 l6 L1 h7 E { 6 V3 A0 f, \; m) }+ a) N; P- F3 ?
dims[1]=k;
" A* p3 I4 s3 m index=mxCalcSingleSubscript(prhs,ndim,dims);
7 t/ i+ j- Z! N/ g if (pi==NULL)
. N9 {$ i/ t' [6 I( P2 r+ N0 i { % l. Z* q# q1 w
mexPrintf("%6.2f",pr[index]); 7 N; O( @/ P _& q9 U. n
}
3 {( z- p1 K, V5 b0 F4 D) N else{ $ x1 B3 ]! }, s- b; p i. Q
mexPrintf("%6.2f+ %6.2fj",pr[index],pi[index]);
: _/ n! W0 V6 i' l! S" M } 3 i K! M- o* r2 K- C
}
4 N U: w+ x3 r0 n mexPrintf("\n");
$ o; ]% M5 u* j" ^3 u/ j
& h4 b/ T" h0 [! j- P } - o$ ~9 b8 E! ]
4 ^$ g2 {; O# U5 K) i- X. Z } # \+ v6 n H+ Y4 W! S, j
else{ 9 {. z8 v. ~1 `+ X" t1 C( |
mexPrintf("input NUMB %d matrix is not 2 dims&double numerical array\n",i); . ?" }% a& f6 L; t
}
- i: S4 c1 {. Q/ I$ j. D 6 ]6 K+ s: D# t* n# ^
# m; w. d. e$ w! `/ b) C+ O
}
1 e( y& j, {7 d8 W( F! e 8 g L% _" _! H$ J; \- B8 u3 \
} ( E8 c+ M7 ^0 \
- B: q' q! j& c5 _- ] Result:
5 d3 ^+ k. @% H0 @( }
" Z% [0 C: l& M3 [# O0 z >>mex test.cpp % J+ G+ I1 {* ?9 c+ \) t/ Y
>> test(a,b,c)
$ h0 e4 \. h, c% b 变量0: " k" P. E: L) W8 X
0.35 0.62 0.83
; u i) ?' [6 q7 J& x" l1 R 0.20 0.47 0.59 R/ ?7 L& f% Y# s; y# k
0.25 0.35 0.55
* k0 ]* V# L# s4 b 变量1:
2 e X5 B9 A" s9 H# R8 E 0.92 0.38 0.53 0.57 2 |7 E* ]: ^0 s F; B
0.29 0.57 0.78 0.47 : X$ X5 v5 A* [7 q! X- z
0.76 0.08 0.93 0.01
/ Z7 d M) u B1 r+ q" y* Q0 @ 0.75 0.05 0.13 0.34 6 i9 w+ J6 ^7 m1 {% E
变量2:
$ x2 _" Y- T) Q* A 0.16+ 0.87j 0.60+ 0.43j 0.45+ 0.14j 0.83+ 0.85j 0.11+ 0.08j , U n% U9 @% F
0.79+ 0.08j 0.26+ 0.91j 0.08+ 0.87j 0.54+ 0.62j 0.96+ 0.24j
3 i; \$ E4 L0 N4 S 0.31+ 0.40j 0.65+ 0.18j 0.23+ 0.58j 1.00+ 0.35j 0.00+ 0.12j ; {: O" F0 O! f8 e+ S
0.53+ 0.26j 0.69+ 0.26j 0.91+ 0.55j 0.08+ 0.51j 0.77+ 0.18j
) U. K; b" t. V8 U0 E7 A, H 0.17+ 0.80j 0.75+ 0.15j 0.15+ 0.14j 0.44+ 0.40j 0.82+ 0.24j . N# i/ h7 g2 C
>> help test , d0 i5 a8 X, f) l, W- B
本程序用于调试mx______ 函数 .
7 r3 j* w" H& [ % E$ R$ Y" ^ ]* o4 Z0 W
6 @2 v7 O& f, `& p z2 W6 l 本文来自: 高校自动化网 (Www.zdh1909.com ) 详细出处参考 ( 转载请保留本链接 ) : http://www.zdh1909.com/html/matlab/14744.html
, Y& ?; r0 Z. m) o4 w8 X1 Y5 m$ B
9 Z B) w. o; a' k 下面是其附件,内容一样,方便下载
Matlab调用c程序.doc
(41.5 KB, 下载次数: 10)
zan
总评分: 体力 + 5
查看全部评分