版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
4.1MEX文件简介
4.2管理MATLAB数据4.3可视化创建MEX文件4.4MEX文件示例练习
第4章创建Fortran语言MEX文件4.1MEX文件简介第4章创建Fortran语言M14.1MEX文
件
简
介
4.1.1简单的MEX文件示例
在详细介绍Fortran语言MEX文件的编写方法之前,首先查看一个简单的Fortran语言MEX源文件,通过该文件了解Fortran语言MEX文件的基本创建过程。下面是该文件的源代码。
4.1MEX文件简介4.1.1简单的MEX2<例4-1简单的Fortran语言MEX文件——mexHelloWorld.f。001 C入口函数002 subroutinemexFunction(nlhs,plhs,nrhs,prhs)003C-----------------------------------------------004 C 参数声明005 integerplhs(*),prhs(*)006 integernlhs,nrhs007 C 代码行008 callmexPrintf('HelloMATLABWorld!')009 C 函数文件尾部010 return011 end<例4-1简单的Fortran语言MEX文件——mex3和例3-1类似,例4-1的代码功能也是在MATLAB命令行窗口中输出一段文字。首先请读者使用任何一种能够编辑纯文本文件的编辑器,将上面的代码键入到文件中。注意,不要将行号(001~011)也敲进去,在这里设置行号的主要目的是为了便于讲解和分析程序。然后将该文件保存,设置文件名称为mexHelloWorld.f(Fortran语言源文件的文件扩展名为.f),将该文件拷贝或者保存到MATLAB的当前工作路径下。接着,在MATLAB的命令行窗口下键入下面的指令:>>mexmexHelloWorld.f和例3-1类似,例4-1的代码功能也是在MATLAB命4如果编辑的应用程序没有任何错误,则MATLAB命令行中不会显示任何消息;否则,在MATLAB命令行中将显示相应的错误消息提示。如果出现编译错误,请仔细查看键入的源程序代码,修改错误直到编译通过为止。另外,再次强调配置编译器的时候选择MATLAB支持的Fortran语言编译器。编译的结果是创建出MATLAB的MEX文件,可以在MATLAB命令行下键入what指令查看当前路径下是否具有MEX文件。
如果编辑的应用程序没有任何错误,则MATLAB命令行中不5>>whatMEX-filesinthecurrentdirectoryD:\TempmexHelloWorld接着,运行创建的MEX文件,在MATLAB命令行中键入下面的指令:>>mexHelloWorldHelloMATALBWorld!>>what64.1.2MEX源文件的基本结构花费一点时间查看一下Fortran语言MEX源文件的基本结构。Fortran语言MEX源文件是标准的Fortran语言源文件,建议读者在创建Fortran语言MEX源文件的时候使用Fortran77或者Fortran90的语言标准,以符合不同Fortran编译器的要求,这样编写出来的源代码就会具有比较好的可移植性。
4.1.2MEX源文件的基本结构7从程序的第001行开始到006行,都是Fortran语言MEX源文件入口函数的声明部分:C入口函数subroutinemexFunction(nlhs,plhs,nrhs,prhs)C-------------------------------------------------C 参数声明integerplhs(*),prhs(*)integernlhs,nrhsmexFunction函数类似C语言源文件的main函数,它是MEX文件的入口函数。当在MATLAB命令行中执行MEX函数时,MATLAB解释器将从此函数处开始执行MEX代码。
从程序的第001行开始到006行,都是Fortran语言8该入口函数的输入参数有四个,其意义分别是:nlhs:表示输入参数的个数。Plhs:mxArray类型的指针数组,表示MEX函数的输入参数。Nrhs:表示输出参数的个数。Prhs:mxArray类型的指针数组,表示MEX函数的输出参数。
该入口函数的输入参数有四个,其意义分别是:9其实上述输入、输出参数的名称非常容易记忆,lhs代表Lefthandparameters,rhs代表righthandparameters,n代表number,p代表pointer。这里的左手和右手如何划分呢?例如在MATLAB中调用求伯特图的函数时,可以这样调用:[mag,phase,w]=bode(sys)这里以“=”为分界,左边的参数mag、phase和w为输出参数,即左手参数,而等号右边的参数sys,为输入参数,即右手参数。
其实上述输入、输出参数的名称非常容易记忆,lhs代表Le10入口函数之后就是Fortran语言MEX源文件的程序主体部分了,在这里需要完成MATLAB数据的获取和内存的分配,调用相应的计算子程序或者函数,完成MEX文件的计算工作,最后将必要的输出返回给MATLAB。程序的结尾是Fortran语言的特别要求,必须有return和end关键字作为Fortran语言源程序的结束。
入口函数之后就是Fortran语言MEX源文件的程序主体114.2管理MATLAB数据
相比较而言在C语言中管理MATLAB的数据是比较容易的,而在Fortran中,由于受到编程语言本身的限制,就没有C语言那么灵活的方法,不过MATLAB还是提供了相应的mx函数用于Fortran语言程序的开发。注意,这些Fortran语言的mx函数不仅可以用于MEX文件的编写,而且还可以用于其它的应用程序开发。首先,查看一个Fortran语言MEX文件的应用实例,该例子是对例4-2——simple.c使用Fortran语言重新编写而得的。
4.2管理MATLAB数据相比较而言在C语言中管理12<例4-2简单的MEX文件示例——simple.f。001 C==========================================002 C Simple.f003 C AsimplemexfiledemobyFortran004 C 20031010005 C==========================================006 CNumbericAssignment007 subroutineAssignNumericData(pr)008 integerpr009 real*8rdata(6)010 datardata/1.,2.,3.,4.,5.,6./<例4-2简单的MEX文件示例——simple.f。13011 012 callmxCopyReal8ToPtr(rdata,pr,6)013 014 return015 end016 017 CThegatewayroutine018 subroutinemexFunction(nlhs,plhs,nrhs,prhs)019 C-------------------------------------------------020 C(pointer)Replaceintegerbyinteger*8ontheDECAlpha021 C64-bitplatform.022011 14023 integerplhs(*),prhs(*)024 integermxGetPr,mxCreateDoubleMatrix025 integerpr026 C--------------------------------------------027 integernlhs,nrhs028 029 CCheckforpropernumberofarguments.030 if(nlhs.ne.1)then031 callmexErrMsgTxt('Oneoutputrequired.')032 endif033023 integerplhs(*),prh15034 CCreatematrixforthereturnargument.035 plhs(1)=mxCreateDoubleMatrix(2,3,0)036 CGetthepointtotheOutputargument 037 pr=mxGetPr(plhs(1))038 CCalltheAssignmentSubroutine039 callAssignNumericData(pr)040 CFinished!041 return042 end034 CCreatematrixforth16例4-2的代码是更完整的Fortran语言的MEX函数文件应用,此程序可以分为如下部分:首先从程序的007~015行是赋值运算的子函数,该函数在入口函数中调用,调用的代码在038行。与一般的C语言MEX文件不同,C语言的MEX文件直接利用memcpy函数完成数据的拷贝(复制),而Fortran语言本身没有提供这样的函数,于是在simple.f的源代码中,使用了mxCopy函数完成mxArray数据和Fortran语言数据的交互。这个函数就是在012行调用的mxCopyReal8ToPtr,该函数的定义如下:subroutinemxCopyReal8ToPtr(y,px,n)real*8y(n)integer*4px,n例4-2的代码是更完整的Fortran语言的MEX函数文17其中,y为双精度类型的实数数组,其元素的个数为n,而px则为mxArray数据对象的数据指针,在Fortran语言中使用整数类型表示。该函数的功能就是将实数数组y中的元素都赋值给mxArray数据对象px,与之对应的函数是mxCopyPtrToReal8,该函数的说明请参阅MATLAB的帮助文档。
其中,y为双精度类型的实数数组,其元素的个数为n,而px18编译并运行例4-2的代码:>>mexsimple.f>>simple???Oneoutputrequired.Errorin==>D:\Temp\simple.dll>>y=simpley=135246编译并运行例4-2的代码:19与C语言的mx函数不同,在MATLAB提供的Fortran语言mx函数中专门有十几个函数用来完成MATLAB数据指针的操作,分别可以用来操作字符串、双精度数组以及稀疏矩阵等。例如在例4-2的代码中使用了操作双精度数据的mxCopy函数。另外,在MATLAB的帮助文档中也提供了很多丰富的Fortran语言的应用实例,分别说明了操作各种数据的方法,请读者仔细阅读相应的帮助文档信息。
与C语言的mx函数不同,在MATLAB提供的Fort204.3可视化创建MEX文件
可视化创建Fortran语言的MEX文件需要使用可视化的Fortran开发环境,这里笔者推荐使用CompaqVisualFortran,它的图形化开发界面和VisualStudio6的界面保持一致,使用起来也和VisualC++6一样,几乎可以做到无缝的过渡,也就是熟悉使用VisualC++6的用户,基本上不需要什么额外的工作,就可以利用熟悉的Fortran语言开发应用程序了。
4.3可视化创建MEX文件可视化创建Fortr21图4-1创建Fortran语言项目文件
图4-1创建Fortran语言项目文件22在“Projectname”处设置项目的名称为“mexfilename”,单击“OK”按钮创建新的工程项目。
注意:如果用户的计算机上安装了VisualC++和CompaqVisualFortran,则两种开发工具共用一种开发界面,不过在具体开发应用程序的时候,分别使用自己的高级语言编译器。然后,在弹出的对话框中选择“AnemptyDLLapplication”单选框,如图4-2所示。
在“Projectname”处设置项目的名称为“mex23图4-2选择创建空DLL文件应用
图4-2选择创建空DLL文件应用24单击“Finish”按钮,完成项目的创建。创建新的项目之后,则需要向项目中添加资源文件——mexversion.rc,该文件位于%MATLABROOT%\extern\include路径中,该文件定义了MATLAB的MEX文件版本信息,然后再添加MEX源文件,例如simple.f。
单击“Finish”按钮,完成项目的创建。25第三步,创建DEF文件,该文件的内容如下:LIBRARYMYFILE.DLLEXPORTS_MEXFUNCTION@16注意,在这里创建的DEF文件和在创建C语言MEX文件时定义的DEF文件的内容不同。第四步,执行“Tools”菜单下的“Options”命令,在弹出的对话框中设置Library的路径,将E:\MATLAB6p5p1\EXTERN\LIB\WIN32\DIGITAL\DF60路径添加到该对话框中,如图4-3所示。
第三步,创建DEF文件,该文件的内容如下:26图4-3设置Library路径
图4-3设置Library路径27按Alt+F7键,或者执行“Project”菜单下的“Setting”命令,在弹出的对话框中将必要的Lib文件添加在Link页的属性设置中。所谓必要的Lib文件,主要是mx函数的libmx.lib和mex函数的libmex.lib,如果使用MAT数据文件应用函数,则还需要将libmat.lib文件添加到属性中。关于MAT数据文件的应用将在第5章中详细讲解。设置Link属性对话框,如图4-4所示。
按Alt+F7键,或者执行“Project”菜单下的“S28图4-4设置Link属性,添加必要的Lib文件
图4-4设置Link属性,添加必要的Lib文件29单击“OK”按钮结束属性的设置,然后,设置C/C++预处理编译命令,设置该属性为MATLAB_MEX_FILE。接着就可以直接按F7键,或者执行“Build”菜单下的“Buildmexfilename.dll”命令,来完成MEX文件的创建。
单击“OK”按钮结束属性的设置,然后,设置C/C++预30如果用户需要在CompaqVisualFortran的开发环境中进行Fortran语言的MEX文件可视化调试,则可以在创建完毕工程项目后,在源文件中需要设置断点的位置设置断点,然后执行“Build”菜单下“StartDebug”子菜单下的“Go”命令,或者直接按F5键,这时CompaqVisualFortran将弹出对话框,如图4-5所示。
如果用户需要在CompaqVisualFortran31图4-5设置可执行文件的对话框
图4-5设置可执行文件的对话框324.4MEX文
件
示
例
<例4-3创建稀疏矩阵。首先向读者演示一个创建稀疏矩阵的例子,该例子其实是第2章创建稀疏矩阵C语言例子的翻版,这里使用Fortran语言将其重新写了一遍,通过这个例子重点了解一下mxCopy函数的具体使用方法,下面是该例子的源代码:
4.4MEX文件示例<例4-3创建稀33001 C fcreatesparse.f002 C 创建稀疏矩阵003 C 入口函数004 subroutinemexFunction(nlhs,plhs,nrhs,prhs)005 C------------------------------------------006 C 参数声明007 integerplhs(*),prhs(*)008 integernlhs,nrhs009 C 指针010 integerir,jc,pr011 C 实际数据
012 real*8pdata(6)001 C fcreatesparse.f34013 datapdata/3,1,10,-7,2,-2/014 integerirdata(6)015 datairdata/0,3,0,1,2,3/016 integerjcdata(5)017 datajcdata/0,2,2,5,6/018 C------------------------------------------019 integermxGetIr,mxGetJc,mxGetPr020 integermxCreateSparse021 integermxCopyReal8ToPtr022 integermxCopyInteger4ToPtr023 C 代码行
013 datapdata/3,1,10,-735024 plhs(1)=mxCreateSparse(4,4,6,0)025 ir=mxGetIr(plhs(1))026 jc=mxGetJc(plhs(1))027 pr=mxGetPr(plhs(1))028 C 内存复制029 callmxCopyReal8ToPtr(pdata,pr,6)030 callmxCopyInteger4ToPtr(irdata,ir,6)031 callmxCopyInteger4ToPtr(jcdata,jc,5)032 C 函数文件尾部033 return034 end024 plhs(1)=mxCreateSparse36本例子的核心部分从024行开始,首先使用mxCreateSparse函数创建了稀疏矩阵的mxArray数据对象,然后分别使用mxGetIr、mxGetJc、mxGetPr三个函数获取稀疏矩阵的三个重要的指针ir、jc和pr,这里是实数的稀疏矩阵,所以没有pi指针。接着,使用mxCopy函数完成数据内存的复制。这里需要用户注意的是整数类型的数据拷贝,在MATLAB的外部接口函数库中,具有三个不同的函数用于整数类型数据的拷贝,分别是:●mxCopyInteger1ToPtr。●mxCopyInteger2ToPtr。●mxCopyInteger4ToPtr。
本例子的核心部分从024行开始,首先使用mxCreate37同样,还有三个函数用于将指针数据拷贝给相应的整数类型数据,这里就不一一列举了。需要读者注意的是,针对具体的整数数据类型须选取不同的拷贝函数。下面编译运行该文件:>>mexfcreatesparse.f>>A=fcreatesparseA=(1,1)3(4,1)1(1,3)10(2,3) -7同样,还有三个函数用于将指针数据拷贝给相应的整数类型38(3,3)2(4,4)-2>>full(A)ans=3010000-700020100-2(3,3)239<例4-4复数数据。Fortran语言的数据类型是比较丰富的,其中,其独有的复数数据类型是该语言的一个优势,使其成为了早期计算机数值编程领域首选的编程语言。在MATLAB中,同样有相应的数据类型,不过Fortran语言的复数和MATLAB的复数之间进行交互的时候,只能够通过mxCopy函数完成数据的传递。例4-4演示了Fortran语言MEX文件处理复数的方法。下面是程序的源代码:
<例4-4复数数据。40001 C========================================002 Ctimes2.f003 C将输入的数据乘以2.004 C005 C简单的MEX文件示例.006 C=========================================007 C算法子程序008 subroutinetimes2(y,x,size)009 complex*16x(*),y(*)010 integersize011 do10,i=1,size001 C========================41012 y(i)=2.0*x(i)013 10continue014 return015 end016 017 C入口函数018 subroutinemexFunction(nlhs,plhs,nrhs,prhs)019 C----------------------------------------020 C(pointer)Replaceintegerbyinteger*8ontheDECAlpha021 C64-bitplatform.012 y(i)=2.0*x(i)42022 023 integerplhs(*),prhs(*)024 integermxGetPr,mxGetPi,mxCreateDoubleMatrix025 integerx_pr,x_pi,y_pr,y_pi026 C----------------------------------------027 integernlhs,nrhs028 integermxIsComplex029 integerm,n,size030 complex*16x(100),y(100)031 032 C检查输入参数是否满足需要
022 43033 if(nrhs.ne.1)then034 callmexErrMsgTxt('Oneinputrequired.')035 elseif(nlhs.ne.1)then036 callmexErrMsgTxt('Oneoutputrequired.')037 endif038 039 C获取输入的数据尺寸040 m=mxGetM(prhs(1))041 n=mxGetN(prhs(1))042 size=m*n043 044 C确认输入的数据是否为合适的类型
033 if(nrhs.ne.1)then44045 if(mxIsComplex(prhs(1)).eq.0)then046 callmexErrMsgTxt('Inputmustbeacomplex.')047 endif048 C获取输入的数据指针049 x_pr=mxGetPr(prhs(1))050 x_pi=mxGetPi(prhs(1))051 callmxCopyPtrToComplex16(x_pr,x_pi,x,size)052 053 C调用计算子程序054 calltimes2(y,x,size)055 C创建返回的参数
056 plhs(1)=mxCreateDoubleMatrix(m,n,1)045 if(mxIsComplex(prhs(1)).45057 y_pr=mxGetPr(plhs(1))058 y_pi=mxGetPi(plhs(1))059 060 C复制数据到输出参数061 callmxCopyComplex16ToPtr(y,y_pr,y_pi,size)062 063 return064 end057 y_pr=mxGetPr(plhs(46在Fortran语言的MEX函数文件中,如果需要操作复数,则需要使用mxCopyPtrToComplex16函数将指针拷贝给复数数组,而使用mxCopyComplex16ToPtr函数将复数数组拷贝给指针,这两个函数的定义分别如下:subroutinemxCopyPtrToComplex16(pr,pi,y,n)complex*16y(n)integer*4pr,pi,nsubroutinemxCopyComplex16ToPtr(y,pr,pi,n)complex*16y(n)integer*4pr,pi,n在Fortran语言的MEX函数文件中,如果需要操作47在上述的两个函数中,y代表Fortran语言的复数数组,而pr和pi为mxArray数据对象中保存数据的两个指针。在例4-4的代码中,分别在051行和061行调用了这两个函数,完成了复数矩阵的处理。编译运行例4-4:>>mextimes2.f>>A=[1+2i,1-2i;2+1i,2-1i]A=1.0000+2.0000i1.0000-2.0000i2.0000+1.0000i2.0000-1.0000i在上述的两个函数中,y代表Fortran语言的复数数组,48>>B=times2(A)B=2.0000+4.0000i2.0000-4.0000i4.0000+2.0000i4.0000-2.0000i>>C=times2(B(1:4))C=Columns1through34.0000+8.0000i8.0000+4.0000i4.0000-8.0000iColumn48.0000-4.0000i>>B=times2(A)49>>whosNameSizeBytesClassA2x264doublearray(complex)B2x264doublearray(complex)C1x464doublearray(complex)Grandtotalis12elementsusing192bytes可以看到,例4-4的代码可以处理矩阵和向量,但输入的参数必须为复数。>>whos可以看到,例4-4的代码可以处理矩阵和向量50<例4-5处理字符串。字符串永远是一类特殊的数据类型,在Fortran语言的MEX文件中也是如此。例4-5的代码演示了在Fortran语言的MEX函数文件中处理字符串的一些方法和函数。请读者注意,字符串在高级语言中一般占用一个字节的内存,而MATLAB的字符串占用两个字节的内存,因此,程序的输出比输入少一半也就不足为奇了。下面是例4-5程序的源代码:<例4-5处理字符串。51001 Cparsestring.f002 C算法函数003 subroutinerevord(input_buf,strlen,output_buf)004 characterinput_buf(*),output_buf(*)005 integeri,strlen006 C倒置字符串007 do10i=1,strlen008 output_buf(i)=input_buf(strlen-i+1)10continue010 011 return012 end001 Cparsestring.f52013 C入口函数014 subroutinemexFunction(nlhs,plhs,nrhs,prhs)015 C--------------------------------------------------------------016 C 参数声明017 integerplhs(*),prhs(*)018 integernlhs,nrhs019 integermxCopyCharacterToPtr,mxCreateCharArray,mxGetPr020 integermxGetM,mxGetN,mxGetString021 character*32input_buf022 character*32output_buf023 integerdims(2)024 integerpr025 integerm,n,size013 C入口函数53026 C---------------------------------------------------------------027 C代码行028 if(nrhs.ne.1)then029 callmexErrMsgTxt('Oneinputrequired.')030 elseif(nlhs.ne.1)then031 callmexErrMsgTxt('Oneoutputrequired.')032 endif033 C判断输入的参数尺寸034 m=mxGetM(prhs(1))035 n=mxGetN(prhs(1))036 size=m*n037 if(size.gt.30)then038 callmexErrMsgTxt('Toolongoftheinputstring!')039 endif026 C-------------------------54040 C获取字符串041 callmxGetString(prhs(1),input_buf,size)042 043 output_buf=''044 C调用算法函数045 callrevord(input_buf,size,output_buf)046 C创建输出参数047 dims(1)=5048 dims(2)=3049 plhs(1)=mxCreateCharArray(2,dims)040 C获取字符串55050 C获取指针051 pr=mxGetPr(plhs(1))052 C拷贝数据053 callmxCopyCharacterToPtr(output_buf,pr,30)054 C函数文件的尾部055 return056 end050 C获取指针56例4-5的函数文件对字符串的操作使用了两个不同的函数,分别为mxGetString函数和mxCopyCharacterToPtr函数,这两个函数以及mxCopyPtrToCharacter函数都可以处理字符串,但是,从使用的难易角度上看,mxGetString函数更值得使用,这个函数相对简单容易。编译运行例4-5:>>mexparsestring.f>>str=parsestring('ABCDEFGHIJKLMN!')str=!JENIDMHCLGB例4-5的函数文件对字符串的操作使用了两个不同的函数,分57KFA>>str=parsestring('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234')str=4TJ2RHZPFXNDVLBKFA58<例4-6清除MEX文件的操作。mex函数中提供了锁定和解锁函数,被锁定的mex函数不能从内存中清除,而解锁之后才能够从内存中将函数文件清除。另外,mexAtExit函数可以用来向MATLAB注册函数,注册的函数将在MEX文件从内存中清除时被自动调用,从而可以完成一些清除内存,释放空间的操作。例4-6演示了锁定函数mexLock和解锁函数mexUnlock的使用方法,mexAtExit函数注册的函数可以帮助读者了解clearall操作是否真的将函数清除。下面是程序的源代码:<例4-6清除MEX文件的操作。59001 Cmexlocked.f002 CDemofileaboutmexlock&mexunlock003 C入口函数004 subroutinemexFunction(nlhs,plhs,nrhs,prhs)005 C--------------------------------------------------------------006 C参数声明007 externalcloseup008 integerplhs(*),prhs(*)009 integernlhs,nrhs010 integermexIsLocked011 real*8mxGetScalar012 real*8lock001 Cmexlocked.f60013 integerstatus014 C代码行015 status=mexAtExit(closeup)016 if(status.ne.0)then017 callmexErrMsgTxt(018 *'RegisterExitsubroutineerror!')019 endif020 C参数检查021 if(nrhs.ne.1)then022 callmexErrMsgTxt(023 *'Inputargumentmustbearealscalardouble')024 elseif((mxIsDouble(prhs(1)).ne.1).or.013 integerstatus61025 *(mxGetN(prhs(1))*mxGetM(prhs(1)).ne.1).or.026 *(mxIsComplex(prhs(1)).eq.1))then027 callmexErrMsgTxt(028 *'Inputargumentmustbearealscalardouble')029 endif030 if(nlhs.gt.0)then031 callmexErrMsgTxt('Nooutputargumentsexpected.')032 endif033 034 lock=mxGetScalar(prhs(1))035 C参数检查025 *(mxGetN(prhs(1))62036 if((lock.ne.0.0).and.(lock.ne.1.0).and.037 *(lock.ne.-1.0))then038 callmexErrMsgTxt('Inputargumentmustbeeither1039 *tolockor-1tounlockor0forlockstatus.')040 endif041 C锁定操作042 if(mexIsLocked().eq.1)then043 if(lock.gt.0.0)then044 callmexWarnMsgTxt('MEX-fileisalreadylocked')045 elseif(lock.lt.0.0)then046 callmexUnlock()047 callmexPrintf('MEX-fileisunlocked')036 if((lock.ne.0.0)63048 else049 callmexPrintf('MEX-fileislocked')050 endif051 else052 if(lock.lt.0.0)then053 callmexWarnMsgTxt('MEX-fileisalreadyunlocked')054 elseif(lock.gt.0.0)then055 callmexLock()056 callmexPrintf('MEX-fileislocked')057 else058 callmexPrintf('MEX-fileisunlocked')059 endif060 endif048 else64061 C函数文件尾部062 return063 end064 C清除函数 065 subroutinecloseup()066 callmexPrintf('ExittheMEXfile')067 end061 C函数文件尾部65编译运行例4-6:>>mexmexlocked.f>>%锁定MEX文件>>mexlocked(1)MEX-fileislocked>>%不允许再次锁定>>mexlocked(1)Warning:MEX-fileisalreadylocked>>%从内存中清除MEX文件操作>>clearall>>%无法成功,因为MEX文件被锁定>>mexlocked(1)编译运行例4-6:66Warning:MEX-fileisalreadylocked>>%解锁>>mexlocked(-1)MEX-fileisunlocked>>%再次清除>>clearallExittheMEXfile>>%操作成功!Warning:MEX-fileisalreadyl67练习1.比较C语言MEX文件和Fortran语言MEX文件的异同点。2.使用Fortran语言MEX文件,重新编写例3-10设置图像属性的代码,要求能够在MEX文件中直接创建曲线,并且设置曲线的属性,可以在集成开发环境中完成程序的编译过程。3.使用Fortran语言MEX文件编写第2章练习3的代码,创建整数类型的矩阵即可。
4.编写程序完成下列功能:调用MATLAB指令,根据输入的参数计算矩阵的特征值和特征向量(如果输入的参数是双精度类型矩阵,则利用MATLAB的矩阵运算指令)。练习1.比较C语言MEX文件和Fortra684.1MEX文件简介
4.2管理MATLAB数据4.3可视化创建MEX文件4.4MEX文件示例练习
第4章创建Fortran语言MEX文件4.1MEX文件简介第4章创建Fortran语言M694.1MEX文
件
简
介
4.1.1简单的MEX文件示例
在详细介绍Fortran语言MEX文件的编写方法之前,首先查看一个简单的Fortran语言MEX源文件,通过该文件了解Fortran语言MEX文件的基本创建过程。下面是该文件的源代码。
4.1MEX文件简介4.1.1简单的MEX70<例4-1简单的Fortran语言MEX文件——mexHelloWorld.f。001 C入口函数002 subroutinemexFunction(nlhs,plhs,nrhs,prhs)003C-----------------------------------------------004 C 参数声明005 integerplhs(*),prhs(*)006 integernlhs,nrhs007 C 代码行008 callmexPrintf('HelloMATLABWorld!')009 C 函数文件尾部010 return011 end<例4-1简单的Fortran语言MEX文件——mex71和例3-1类似,例4-1的代码功能也是在MATLAB命令行窗口中输出一段文字。首先请读者使用任何一种能够编辑纯文本文件的编辑器,将上面的代码键入到文件中。注意,不要将行号(001~011)也敲进去,在这里设置行号的主要目的是为了便于讲解和分析程序。然后将该文件保存,设置文件名称为mexHelloWorld.f(Fortran语言源文件的文件扩展名为.f),将该文件拷贝或者保存到MATLAB的当前工作路径下。接着,在MATLAB的命令行窗口下键入下面的指令:>>mexmexHelloWorld.f和例3-1类似,例4-1的代码功能也是在MATLAB命72如果编辑的应用程序没有任何错误,则MATLAB命令行中不会显示任何消息;否则,在MATLAB命令行中将显示相应的错误消息提示。如果出现编译错误,请仔细查看键入的源程序代码,修改错误直到编译通过为止。另外,再次强调配置编译器的时候选择MATLAB支持的Fortran语言编译器。编译的结果是创建出MATLAB的MEX文件,可以在MATLAB命令行下键入what指令查看当前路径下是否具有MEX文件。
如果编辑的应用程序没有任何错误,则MATLAB命令行中不73>>whatMEX-filesinthecurrentdirectoryD:\TempmexHelloWorld接着,运行创建的MEX文件,在MATLAB命令行中键入下面的指令:>>mexHelloWorldHelloMATALBWorld!>>what744.1.2MEX源文件的基本结构花费一点时间查看一下Fortran语言MEX源文件的基本结构。Fortran语言MEX源文件是标准的Fortran语言源文件,建议读者在创建Fortran语言MEX源文件的时候使用Fortran77或者Fortran90的语言标准,以符合不同Fortran编译器的要求,这样编写出来的源代码就会具有比较好的可移植性。
4.1.2MEX源文件的基本结构75从程序的第001行开始到006行,都是Fortran语言MEX源文件入口函数的声明部分:C入口函数subroutinemexFunction(nlhs,plhs,nrhs,prhs)C-------------------------------------------------C 参数声明integerplhs(*),prhs(*)integernlhs,nrhsmexFunction函数类似C语言源文件的main函数,它是MEX文件的入口函数。当在MATLAB命令行中执行MEX函数时,MATLAB解释器将从此函数处开始执行MEX代码。
从程序的第001行开始到006行,都是Fortran语言76该入口函数的输入参数有四个,其意义分别是:nlhs:表示输入参数的个数。Plhs:mxArray类型的指针数组,表示MEX函数的输入参数。Nrhs:表示输出参数的个数。Prhs:mxArray类型的指针数组,表示MEX函数的输出参数。
该入口函数的输入参数有四个,其意义分别是:77其实上述输入、输出参数的名称非常容易记忆,lhs代表Lefthandparameters,rhs代表righthandparameters,n代表number,p代表pointer。这里的左手和右手如何划分呢?例如在MATLAB中调用求伯特图的函数时,可以这样调用:[mag,phase,w]=bode(sys)这里以“=”为分界,左边的参数mag、phase和w为输出参数,即左手参数,而等号右边的参数sys,为输入参数,即右手参数。
其实上述输入、输出参数的名称非常容易记忆,lhs代表Le78入口函数之后就是Fortran语言MEX源文件的程序主体部分了,在这里需要完成MATLAB数据的获取和内存的分配,调用相应的计算子程序或者函数,完成MEX文件的计算工作,最后将必要的输出返回给MATLAB。程序的结尾是Fortran语言的特别要求,必须有return和end关键字作为Fortran语言源程序的结束。
入口函数之后就是Fortran语言MEX源文件的程序主体794.2管理MATLAB数据
相比较而言在C语言中管理MATLAB的数据是比较容易的,而在Fortran中,由于受到编程语言本身的限制,就没有C语言那么灵活的方法,不过MATLAB还是提供了相应的mx函数用于Fortran语言程序的开发。注意,这些Fortran语言的mx函数不仅可以用于MEX文件的编写,而且还可以用于其它的应用程序开发。首先,查看一个Fortran语言MEX文件的应用实例,该例子是对例4-2——simple.c使用Fortran语言重新编写而得的。
4.2管理MATLAB数据相比较而言在C语言中管理80<例4-2简单的MEX文件示例——simple.f。001 C==========================================002 C Simple.f003 C AsimplemexfiledemobyFortran004 C 20031010005 C==========================================006 CNumbericAssignment007 subroutineAssignNumericData(pr)008 integerpr009 real*8rdata(6)010 datardata/1.,2.,3.,4.,5.,6./<例4-2简单的MEX文件示例——simple.f。81011 012 callmxCopyReal8ToPtr(rdata,pr,6)013 014 return015 end016 017 CThegatewayroutine018 subroutinemexFunction(nlhs,plhs,nrhs,prhs)019 C-------------------------------------------------020 C(pointer)Replaceintegerbyinteger*8ontheDECAlpha021 C64-bitplatform.022011 82023 integerplhs(*),prhs(*)024 integermxGetPr,mxCreateDoubleMatrix025 integerpr026 C--------------------------------------------027 integernlhs,nrhs028 029 CCheckforpropernumberofarguments.030 if(nlhs.ne.1)then031 callmexErrMsgTxt('Oneoutputrequired.')032 endif033023 integerplhs(*),prh83034 CCreatematrixforthereturnargument.035 plhs(1)=mxCreateDoubleMatrix(2,3,0)036 CGetthepointtotheOutputargument 037 pr=mxGetPr(plhs(1))038 CCalltheAssignmentSubroutine039 callAssignNumericData(pr)040 CFinished!041 return042 end034 CCreatematrixforth84例4-2的代码是更完整的Fortran语言的MEX函数文件应用,此程序可以分为如下部分:首先从程序的007~015行是赋值运算的子函数,该函数在入口函数中调用,调用的代码在038行。与一般的C语言MEX文件不同,C语言的MEX文件直接利用memcpy函数完成数据的拷贝(复制),而Fortran语言本身没有提供这样的函数,于是在simple.f的源代码中,使用了mxCopy函数完成mxArray数据和Fortran语言数据的交互。这个函数就是在012行调用的mxCopyReal8ToPtr,该函数的定义如下:subroutinemxCopyReal8ToPtr(y,px,n)real*8y(n)integer*4px,n例4-2的代码是更完整的Fortran语言的MEX函数文85其中,y为双精度类型的实数数组,其元素的个数为n,而px则为mxArray数据对象的数据指针,在Fortran语言中使用整数类型表示。该函数的功能就是将实数数组y中的元素都赋值给mxArray数据对象px,与之对应的函数是mxCopyPtrToReal8,该函数的说明请参阅MATLAB的帮助文档。
其中,y为双精度类型的实数数组,其元素的个数为n,而px86编译并运行例4-2的代码:>>mexsimple.f>>simple???Oneoutputrequired.Errorin==>D:\Temp\simple.dll>>y=simpley=135246编译并运行例4-2的代码:87与C语言的mx函数不同,在MATLAB提供的Fortran语言mx函数中专门有十几个函数用来完成MATLAB数据指针的操作,分别可以用来操作字符串、双精度数组以及稀疏矩阵等。例如在例4-2的代码中使用了操作双精度数据的mxCopy函数。另外,在MATLAB的帮助文档中也提供了很多丰富的Fortran语言的应用实例,分别说明了操作各种数据的方法,请读者仔细阅读相应的帮助文档信息。
与C语言的mx函数不同,在MATLAB提供的Fort884.3可视化创建MEX文件
可视化创建Fortran语言的MEX文件需要使用可视化的Fortran开发环境,这里笔者推荐使用CompaqVisualFortran,它的图形化开发界面和VisualStudio6的界面保持一致,使用起来也和VisualC++6一样,几乎可以做到无缝的过渡,也就是熟悉使用VisualC++6的用户,基本上不需要什么额外的工作,就可以利用熟悉的Fortran语言开发应用程序了。
4.3可视化创建MEX文件可视化创建Fortr89图4-1创建Fortran语言项目文件
图4-1创建Fortran语言项目文件90在“Projectname”处设置项目的名称为“mexfilename”,单击“OK”按钮创建新的工程项目。
注意:如果用户的计算机上安装了VisualC++和CompaqVisualFortran,则两种开发工具共用一种开发界面,不过在具体开发应用程序的时候,分别使用自己的高级语言编译器。然后,在弹出的对话框中选择“AnemptyDLLapplication”单选框,如图4-2所示。
在“Projectname”处设置项目的名称为“mex91图4-2选择创建空DLL文件应用
图4-2选择创建空DLL文件应用92单击“Finish”按钮,完成项目的创建。创建新的项目之后,则需要向项目中添加资源文件——mexversion.rc,该文件位于%MATLABROOT%\extern\include路径中,该文件定义了MATLAB的MEX文件版本信息,然后再添加MEX源文件,例如simple.f。
单击“Finish”按钮,完成项目的创建。93第三步,创建DEF文件,该文件的内容如下:LIBRARYMYFILE.DLLEXPORTS_MEXFUNCTION@16注意,在这里创建的DEF文件和在创建C语言MEX文件时定义的DEF文件的内容不同。第四步,执行“Tools”菜单下的“Options”命令,在弹出的对话框中设置Library的路径,将E:\MATLAB6p5p1\EXTERN\LIB\WIN32\DIGITAL\DF60路径添加到该对话框中,如图4-3所示。
第三步,创建DEF文件,该文件的内容如下:94图4-3设置Library路径
图4-3设置Library路径95按Alt+F7键,或者执行“Project”菜单下的“Setting”命令,在弹出的对话框中将必要的Lib文件添加在Link页的属性设置中。所谓必要的Lib文件,主要是mx函数的libmx.lib和mex函数的libmex.lib,如果使用MAT数据文件应用函数,则还需要将libmat.lib文件添加到属性中。关于MAT数据文件的应用将在第5章中详细讲解。设置Link属性对话框,如图4-4所示。
按Alt+F7键,或者执行“Project”菜单下的“S96图4-4设置Link属性,添加必要的Lib文件
图4-4设置Link属性,添加必要的Lib文件97单击“OK”按钮结束属性的设置,然后,设置C/C++预处理编译命令,设置该属性为MATLAB_MEX_FILE。接着就可以直接按F7键,或者执行“Build”菜单下的“Buildmexfilename.dll”命令,来完成MEX文件的创建。
单击“OK”按钮结束属性的设置,然后,设置C/C++预98如果用户需要在CompaqVisualFortran的开发环境中进行Fortran语言的MEX文件可视化调试,则可以在创建完毕工程项目后,在源文件中需要设置断点的位置设置断点,然后执行“Build”菜单下“StartDebug”子菜单下的“Go”命令,或者直接按F5键,这时CompaqVisualFortran将弹出对话框,如图4-5所示。
如果用户需要在CompaqVisualFortran99图4-5设置可执行文件的对话框
图4-5设置可执行文件的对话框1004.4MEX文
件
示
例
<例4-3创建稀疏矩阵。首先向读者演示一个创建稀疏矩阵的例子,该例子其实是第2章创建稀疏矩阵C语言例子的翻版,这里使用Fortran语言将其重新写了一遍,通过这个例子重点了解一下mxCopy函数的具体使用方法,下面是该例子的源代码:
4.4MEX文件示例<例4-3创建稀101001 C fcreatesparse.f002 C 创建稀疏矩阵003 C 入口函数004 subroutinemexFunction(nlhs,plhs,nrhs,prhs)005 C------------------------------------------006 C 参数声明007 integerplhs(*),prhs(*)008 integernlhs,nrhs009 C 指针010 integerir,jc,pr011 C 实际数据
012 real*8pdata(6)001 C fcreatesparse.f102013 datapdata/3,1,10,-7,2,-2/014 integerirdata(6)015 datairdata/0,3,0,1,2,3/016 integerjcdata(5)017 datajcdata/0,2,2,5,6/018 C------------------------------------------019 integermxGetIr,mxGetJc,mxGetPr020 integermxCreateSparse021 integermxCopyReal8ToPtr022 integermxCopyInteger4ToPtr023 C 代码行
013 datapdata/3,1,10,-7103024 plhs(1)=mxCreateSparse(4,4,6,0)025 ir=mxGetIr(plhs(1))
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论