Matlab以MEX方式调用C源代码.docx

上传人:wj 文档编号:2124870 上传时间:2023-05-02 格式:DOCX 页数:9 大小:19.39KB
下载 相关 举报
Matlab以MEX方式调用C源代码.docx_第1页
第1页 / 共9页
Matlab以MEX方式调用C源代码.docx_第2页
第2页 / 共9页
Matlab以MEX方式调用C源代码.docx_第3页
第3页 / 共9页
Matlab以MEX方式调用C源代码.docx_第4页
第4页 / 共9页
Matlab以MEX方式调用C源代码.docx_第5页
第5页 / 共9页
Matlab以MEX方式调用C源代码.docx_第6页
第6页 / 共9页
Matlab以MEX方式调用C源代码.docx_第7页
第7页 / 共9页
Matlab以MEX方式调用C源代码.docx_第8页
第8页 / 共9页
Matlab以MEX方式调用C源代码.docx_第9页
第9页 / 共9页
亲,该文档总共9页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Matlab以MEX方式调用C源代码.docx

《Matlab以MEX方式调用C源代码.docx》由会员分享,可在线阅读,更多相关《Matlab以MEX方式调用C源代码.docx(9页珍藏版)》请在冰点文库上搜索。

Matlab以MEX方式调用C源代码.docx

Matlab以MEX方式调用C源代码

如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:

doubleadd(doublex,doubley)

{

returnx+y;

}

 

现在我想要在Matlab中使用它,比如输入:

 

>>a=add(1.1,2.2)

   3.3000

要得出以上的结果,那应该怎样做呢?

解决方法之一是要通过使用MEX文件,MEX文件使得调用C函数和调用Matlab的内置函数一样方便。

MEX文件是由原C代码加上MEX文件专用的接口函数后编译而成的。

可以这样理解,MEX文件实现了一种接口,它把在Matlab中调用函数时输入的自变量通过特定的接口调入了C函数,得出的结果再通过该接口调回Matlab。

该特定接口的操作,包含在mexFunction这个函数中,由使用者具体设定。

所以现在我们要写一个包含add和mexFunction的C文件,Matlab调用函数,把函数中的自变量(如上例中的1.1和2.2)传给mexFunction的一个参数,mexFunction把该值传给add,把得出的结果传回给mexFunction的另一个参数,Matlab通过该参数来给出在Matlab语句中调用函数时的输出值(如上例中的a)。

值得注意的是,mex文件是与平台有关的,以我的理解,mex文件就是另类的动态链接库。

在matlab6.5中使用mex-v 选项,你可以看到最后mex阶段有类似如下的信息:

-->"del_lib94902.obj"  

-->"del"test.exp""  

-->"del"test.lib""

也就是说,虽然在matlab6.5生成的是dll文件,但是中间确实有过lib文件生成。

比如该C文件已写好,名为add.c。

那么在Matlab中,输入:

>>mexadd.c

就能把add.c编译为MEX文件(编译器的设置使用指令mex-setup),在Windows中,MEX文件类型为mexw32,即现在我们得出add.mexw32文件。

现在,我们就可以像调用M函数那样调用MEX文件,如上面说到的例子。

所以,通过MEX文件,使用C函数就和使用M函数是一样的了。

我们现在来说mexFunction怎样写。

mexFunction的定义为:

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

{

 

}

可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。

mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时:

>>b=1.1;c=2.2;

>>a=add(b,c)

mexFunction四个参数的意思为:

nlhs=1,说明调用语句左手面(lhs-lefthandside)有一个变量,即a。

nrhs=2,说明调用语句右手面(rhs-righthandside)有两个自变量,即b和c。

plhs是一个数组,其内容为指针,该指针指向数据类型mxArray。

因为现在左手面只有一个变量,即该数组只有一个指针,plhs[0]指向的结果会赋值给a。

prhs和plhs类似,因为右手面有两个自变量,即该数组有两个指针,prhs[0]指向了b,prhs[1]指向了c。

要注意prhs是const的指针数组,即不能改变其指向内容。

因为Matlab最基本的单元为array,无论是什么类型也好,如有doublearray、cellarray、structarray……所以a,b,c都是array,b=1.1便是一个1x1的doublearray。

而在C语言中,Matlab的array使用mxArray类型来表示。

所以就不难明白为什么plhs和prhs都是指向mxArray类型的指针数组。

完整的add.c如下:

#include"mex.h"//使用MEX文件必须包含的头文件

//执行具体工作的C函数

doubleadd(doublex,doubley)

{

   returnx+y;

}

//MEX文件接口函数

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

{

   double*a;

   doubleb,c;

   plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);

   a=mxGetPr(plhs[0]);

   b=*(mxGetPr(prhs[0]));

   c=*(mxGetPr(prhs[1]));

   *a=add(b,c);

}

mexFunction的内容是什么意思呢?

我们知道,如果这样调用函数时:

>>output=add(1.1,2.2);

在未涉及具体的计算时,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便是已计算好的结果了。

上面说的一大堆指向这指向那,什么mxArray,初学者肯定都会被弄到头晕眼花了。

很抱歉,要搞清楚这些乱糟糟的关系,只有多看多练。

实际上mexFunction是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保输入正确。

如在add函数的例子中,用户输入chararray便是一种错误了。

从上面的讲述中我们总结出,MEX文件实现了一种接口,把C语言中的计算结果适当地返回给Matlab罢了。

当我们已经有用C编写的大型程序时,大可不必在Matlab里重写,只写个接口,做成MEX文件就成了。

另外,在Matlab程序中的部份计算瓶颈(如循环),可通过MEX文件用C语言实现,以提高计算速度。

以上是对mex文件的初步认识,下面详细介绍如何用c语言编写mex文件:

 

1为什么要用C语言编写MEX文件

 MATLAB是矩阵语言,是为向量和矩阵操作设计的,一般来说,如果运算可以用向量或矩阵实现,其运算速度是非常快的。

但若运算中涉及到大量的循环处理,MATLAB的速度的令人难以忍受的。

解决方法之一为,当必须使用for循环时,把它写为MEX文件,这样不必在每次运行循环中的语句时MATLAB都对它们进行解释。

 2编译器的安装与配置

 要使用MATLAB编译器,用户计算机上应用事先安装与MATLAB适配的以下任何一种ANSIC/C++编译器:

5.0、6.0版的MicroSoftVisualC++(MSVC)

5.0、5.2、5.3、5.4、5.5版的BorlandC++

LCC(由MATLAB自带,只能用来产生MEX文件)

下面是安装与配置MATLAB编译器应用程序MEX的设置的步骤:

(1)在MATLAB命令窗口中运行mex–setup,出现下列提示:

Pleasechooseyourcompilerforbuildingexternalinterface(MEX)files:

Wouldyoulikemextolocateinstalledcompilers[y]/n?

 

(2)选择y,MATLAB将自动搜索计算机上已安装的外部编译器的类型、版本及所在路径,并列出来让用户选择:

Selectacompiler:

[1]BorlandC++Builderversion6.0inC:

\ProgramFiles\Borland

[2]DigitalVisualFortranversion6.0inC:

\ProgramFiles\MicrosoftVisualStudio

[3]LccCversion2.4inD:

\MATLAB6P5P1\sys\lcc

[4]MicrosoftVisualC/C++version6.0inC:

\ProgramFiles\MicrosoftVisualStudio

[0]None

Compiler:

 (3)选择其中一种(在这里选择了3),MATLAB让用户进行确认:

Pleaseverifyyourchoices:

Compiler:

LccC2.4

Location:

D:

\MATLAB6P5P1\sys\lcc

Arethesecorrect?

([y]/n):

 

(4)选择y,结束MATLAB编译器的配置。

3一个简单的MEX文件例子

【例1】用m文件建立一个1000×1000的Hilbert矩阵。

tic

m=1000;

n=1000;

a=zeros(m,n);

fori=1:

1000

    forj=1:

1000

        a(i,j)=1/(i+j);

    end

end

toc

 在matlab中新建一个Matlab_1.cpp文件并输入以下程序:

#include"mex.h"

//计算过程

voidhilb(double*y,intn)

{

   inti,j;

   for(i=0;i

       for(j=0;j

           *(y+j+i*n)=1/((double)i+(double)j+1);

}

//接口过程

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

{

   doublex,*y;

   intn;

 

   if(nrhs!

=1)

       mexErrMsgTxt("Oneinputsrequired.");

   if(nlhs!

=1)

       mexErrMsgTxt("Oneoutputrequired.");

   if(!

mxIsDouble(prhs[0])||mxGetN(prhs[0])*mxGetM(prhs[0])!

=1)

       mexErrMsgTxt("Inputmustbescalars.");

   x=mxGetScalar(prhs[0]);

   plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL);

   n=mxGetM(plhs[0]);

   y=mxGetPr(plhs[0]);

   hilb(y,n);

}

 该程序是一个C语言程序,它也实现了建立Hilbert矩阵的功能。

在MATLAB命令窗口输入以下命令:

mexMatlab_1.cpp,即可编译成功。

进入该文件夹,会发现多了两个文件:

Matlab_1.asv和Matlab_1.dll,其中Matlab_1.dll即是MEX文件。

运行下面程序:

tic

a=Matlab_1(1000);

toc

 elapsed_time=

    0.0470

 由上面看出,同样功能的MEX文件比m文件快得多。

4MEX文件的组成与参数

MEX文件的源代码一般由两部分组成:

(1)计算过程。

该过程包含了MEX文件实现计算功能的代码,是标准的C语言子程序。

(2)入口过程。

该过程提供计算过程与MATLAB之间的接口,以入口函数mxFunction实现。

在该过程中,通常所做的工作是检测输入、输出参数个数和类型的正确性,然后利用mx-函数得到MATLAB传递过来的变量(比如矩阵的维数、向量的地址等),传递给计算过程。

MEX文件的计算过程和入口过程也可以合并在一起。

但不管那种情况,都要包含#include"mex.h",以保证入口点和接口过程的正确声明。

注意,入口过程的名称必须是mexFunction,并且包含四个参数,即:

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

其中,参数nlhs和nrhs表示MATLAB在调用该MEX文件时等式左端和右端变量的个数,例如在MATLAB命令窗口中输入以下命令:

[a,b,c]=Matlab_1(d,e,f,g)

则nlhs为3,nrhs为4。

MATLAB在调用MEX文件时,输入和输出参数保存在两个mxArray*类型的指针数组中,分别为prhs[]和plhs[]。

prhs[0]表示第一个输入参数,prhs[1]表示第二个输入参数,…,以此类推。

如上例中,d→prhs[0],e→prhs[1],f→prhs[2],f→prhs[3]。

同时注意,这些参数的类型都是mxArray*。

接口过程要把参数传递给计算过程,还需要从prhs中读出矩阵的信息,这就要用到下面的mx-函数和mex-函数。

 5常用的mex-函数和mx-函数

在MATLAB6.5版本中,提供的mx-函数有106个,mex-函数有38个,下面我们仅介绍常用的函数。

5.1入口函数mexFunction

该函数是CMEX文件的入口函数,它的格式是固定的:

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

说明:

MATLAB函数的调用方式一般为:

[a,b,c,…]=被调用函数名称(d,e,f,…),nlhs保存了等号左端输出参数的个数,指针数组plhs具体保存了等号左端各参数的地址,注意在plhs各元素针向的mxArray内存未分配,需在接口过程中分配内存;prhs保存了等号右端输入参数的个数,指针数组prhs具体保存了等号右端各参数的地址,注意MATLAB在调用该MEX文件时,各输入参数已存在,所以在接口过程中不需要再为这些参数分配内存。

5.2出错信息发布函数mexErrMsgTxt,mexWarnMsgTxt

两函数的具体格式如下:

#include"mex.h"

voidmexErrMsgTxt(constchar*error_msg);

voidmexWarnMsgTxt(constchar*warning_msg);

其中error_msg包含了要显示错误信息,warning_msg包含要显示的警告信息。

两函数的区别在于mexErrMsgTxt显示出错信息后即返回到MATLAB,而mexWarnMsgTxt显示警告信息后继续执行。

5.3mexCallMATLAB和mexString

两函数具体格式如下:

#include"mex.h"

intmexCallMATLAB(intnlhs,mxArray*plhs[],

intnrhs,mxArray*prhs[],constchar*command_name);

intmexString(constchar*command);

mexCallMATLAB前四个参数的含义与mexFunction的参数相同,command_name可以MATLAB内建函数名、用户自定义函数、M文件或MEX文件名构成的字符串,也可以MATLAB合法的运算符。

mexString用来操作MATLAB空间已存在的变量,它不返回任何参数。

mexCallMATLAB与mexString差异较大,请看下面的例子。

【例2】试用MEX文件求5阶完全图邻接矩阵的特征值及对应的特征向量。

5阶完全图的邻接矩阵为:

(这里找不到图片了,抱歉。

不过不会影响您对本文的理解。

下面是求该矩阵的MEX文件。

[Matlab_2.cpp]

#include"mex.h"

voidmexFunction(intnlhs,mxArray*plhs[],intnrhs,constmxArray*prhs[])

{

   doublex;

   mxArray*y,*z,*w;

   intn;

   if(nrhs!

=1)

       mexErrMsgTxt("Oneinputsrequired.");

   if(nlhs!

=3)

       mexErrMsgTxt("Threeoutputrequired.");

   if(!

mxIsDouble(prhs[0])||mxGetN(prhs[0])*mxGetM(prhs[0])!

=1)

       mexErrMsgTxt("Inputmustbeascalar.");

   x=mxGetScalar(prhs[0]);

   plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL);

   plhs[1]=mxCreateDoubleMatrix(x,x,mxREAL);

   plhs[2]=mxCreateDoubleMatrix(x,x,mxREAL);

   n=mxGetM(plhs[0]);

   y=plhs[0];

   z=plhs[1];

   w=plhs[2];

   //利用mexCallMATLAB计算特征值

   mexCallMATLAB(1,&plhs[1],1,prhs,"ones");

   mexCallMATLAB(1,&plhs[2],1,prhs,"eye");

   mexCallMATLAB(1,&plhs[0],2,&plhs[1],"-");

   mexCallMATLAB(2,&plhs[1],1,&plhs[0],"eig");

   //演示mexString的功能

   mexString("y=y*2");

   mexString("a=a*2");

}

 

在MATLAB命令窗口输入以下命令:

>>mexMatlab_2.cpp

>>clear

>>a=magic(5)

a=

    17    24     1     8    15

    23     5     7    14    16

     4     6    13    20    22

    10    12    19    21     3

    11    18    25     2     9

>>[y,z,w]=Matlab_2(5)

?

?

?

Undefinedfunctionorvariable'y'.

a=

    34    48     2    16    30

    46    10    14    28    32

     8    12    26    40    44

    20    24    38    42     6

    22    36    50     4    18

y=

     0     1     1     1     1

     1     0     1     1     1

     1     1     0     1     1

     1     1     1     0     1

     1     1     1     1     0

z=

    0.8333   -0.1667   -0.1667    0.2236    0.4472

   -0.1667    0.8333   -0.1667    0.2236    0.4472

   -0.1667   -0.1667    0.8333    0.2236    0.4472

   -0.5000   -0.5000   -0.5000    0.2236    0.4472

         0         0         0   -0.8944    0.4472

w=

    -1     0     0     0     0

     0    -1     0     0     0

     0     0    -1     0     0

     0     0     0    -1     0

     0     0     0     0     4

 由上面可以看出,K5的特征值为–1和4,其中–1是四重根。

MATLAB提供了mexGetVariable、mexPutVariable函数,以实现MEX空间与其它空间交换数据的任务,具体可以参看MATLAB帮助文档。

5.4建立二维双精度矩阵函数mxCreateDoubleMatrix

其格式具体如下:

#include"matrix.h"

mxArray*mxCreateDoubleMatrix(intm,intn,mxComplexityComplexFlag);

其中m代表行数,n代表列数,ComplexFlag可取值mxREAL或mxCOMPLEX。

如果创建的矩阵需要虚部,选择mxCOMPLEX,否则选用mxREAL。

 类似的函数有:

 

mxCreateCellArray

创建n维元胞mxArray

mxCreateCellMatrix

创建二维元胞mxArray

mxCreateCharArray

创建n维字符串mxArray

mxCreateCharMatrixFromStrings

创建二维字符串mxArray

mxCreateDoubleMatrix

创建二维双精度浮点mxArray

mxCreateDoubleScalar

创建指定值的二维精度浮点mxArray

mxCreateLogicalArray

创建n维逻辑mxArray,初值为false

mxCreateLogicalMatrix

创建二维逻辑mxArray,初值为false

mxCreateLogicalScalar

创建指定值的二维逻辑mxArray

mxCreateNumericArray

创建n维数值mxArray

mxCreateNumeric

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 成人教育 > 自考

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2