数学建模社区-数学中国
标题:
Matlab调用c程序
[打印本页]
作者:
梦溪517
时间:
2012-8-28 20:47
标题:
Matlab调用c程序
" A2 y2 {$ |/ M! `# Y
Matlab
调用
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/ |
所以现在我们要写一个包含
add
和
mexFunction
的
C
文件,
Matlab
调用函数,把函数中的自变量(如上例中的
1.1
和
2.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( a
void 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 k
mexFunction
四个参数的意思为:
" P' |3 }6 B( s
nlhs = 1
,说明调用语句左手面(
lhs
-
left hand side
)有一个变量,即
a
。
, g) n5 r3 {6 o+ p' L
nrhs = 2
,说明调用语句右手面(
rhs
-
right hand side
)有两个自变量,即
b
和
c
。
$ Q$ z! v2 e$ U7 L: H) T
plhs
是一个数组,其内容为指针,该指针指向数据类型
mxArray
。因为现在左手面只有一个变量,即该数组只有一个指针,
plhs[0]
指向的结果会赋值给
a
。
1 f! d. z' U/ E% N9 A
prhs
和
plhs
类似,因为右手面有两个自变量,即该数组有两个指针,
prhs[0]
指向了
b
,
prhs[1]
指向了
c
。要注意
prhs
是
const
的指针数组,即不能改变其指向内容。
! q$ g! ]5 p2 E; N4 F6 E
因为
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
类型的指针数组。
( 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, V
double 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.1
和
2.2
)取出来赋给
b
和
c
。于是我们可以把
b
和
c
作自变量传给函数
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! E
3 y6 F# u! Z0 J: W
1
、加快程序的执行速度
. Matlab
在
for
上如老牛拉车的速度确实让人抓狂
.
' ?6 N9 `% R8 A+ h- d
# o; _* ^, w+ Q6 q. x6 ]
2
、将
Matlab
作为
C++
的开发调试环境
.
尤其是有大量数据需要处理时
,
用
Matlab
观察其中间结果十分方便
.
, ~# K3 Y6 j2 o3 X" T! k
4 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_t
在
32
位系统上其实本质上就是
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 f
2 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 |$ w
int 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( p
5 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) p
1 `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 N
0.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, E
0.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 t
0.29 0.57 0.78 0.47
$ {1 Y8 F5 j$ T0 u. k Y
0.76 0.08 0.93 0.01
4 [* 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 K
0.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-8-28 20:47 上传
点击文件名下载附件
下载积分: 体力 -2 点
作者:
天海星云
时间:
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