概述
学习笔记。MATLAB自带的timestwo.F文件。
概述
MATLAB调用fortran的程序,需要建立MEX文件。MEX文件是经过编译后的二进制文件。建立了mex文件后,在 MEX 文件中使用 mexFunction,就像在 Fortran 程序中使用 subroutine 一样。
MEX 文件主要有以下用途:
1. 对于大量现有的 C 或者 Fortran 程序可以无须改写成 MATLAB 专用的 M 文件格式而在 MATLAB 中执行。
2. 对于那些 MATLAB 运算速度过慢的算法,可以用 C 或者 Frotran 语言编写以提高效率。
建立MEX文件,首先要撰写源代码,然后利用 mex 命令对源文件进行编译生成MEX文件。语法是:
mex filenames
编译时可以同时编译多个文件,并选择编译器,具体的用法参考MATLAB的帮助文件,搜索“ mex ”。
编写源代码
源代码的基本结构
C 入口程序
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C 声明
C 描述
return
end
编写源代码,可以选择任何一个编辑器,可以使用MATLAB自带的编辑器编写。
首先,需要在源代码第一行插入如下代码:
#include "fintrf.h"
这是一个头文件,里面含有MATLAB接口函数的一些声明。
然后,保存这个文件,并对文件进行命名。MEX源文件的后缀用 .F 表示,源文件的文件名就是MEX文件的文件名,也就是MATLAB调用的fortran函数或子程序的名称。这个例子中,程序名为 timestwo。在使用编译后的MEX文件时,在MATLAB中输入“y = timestwo(x)”即可。
入口程序
每个MEX源文件,都由下面的代码开始
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
其中,plhs, prhs分别表示MEX函数的输出参数数组和输入参数数组,通过mwpointer声明为指针数组,plhs的数组长度为nlhs,prhs的长度为nrhs。
plhs “parameters, left-hand side”
prhs “parameters, right-hand side”
因为MATLAB中函数的形式一般为 [a,b,c,…] = fun(d,e,f,…) 的形式,因此所谓的左手参数就是函数的输出参数,同理,右手参数即为函数的输入参数。
nrhs和nlhs分别记录了输入参数数组和输出参数数组中参数的个数。
当MEX文件编译完成后在 matlab 命令行输入“y = timestwo(x)”时,matlab 便随即加载 timestwo.dll 动态链接库文件。timestwo.dll 加载完成后首先执行 mexFunciton 函数,并把输入参数 x 的值传递给 prhs[0],输入参数的个数“1”传递给 nrhs。
例如,使用 [a,b]=test(c,d,e) 调用mex函数test时,传给test的这四个参数分别是2,plhs,3,prhs。其中:prhs[0]=c,prhs[1]=d,prhs[2]=e,当函数返回时,将会把你放在plhs[0],plhs[1]里的地址赋给a和b,达到返回数据的目的。
prhs[i]和plhs[i]都是指向mxArray类型数据的指针。这个类型是在mex.h中定义的,事实上,在Matlab里大多数数据都是以这种类型存在。
声明
首先是声明MEX函数自身的变量。加入implicit none是很必要的,尤其是对于64位的数组。
implicit none
integer nlhs, nrhs
mwpointer plhs(*), prhs(*)
然后是声明MATLAB的API函数,mwPointer是MATLAB的一个类。
mwPointer mxGetDoubles
mwPointer mxCreateDoubleMatrix
integer mxIsNumeric
mwPointer mxGetM, mxGetN
然后是声明MEX函数的本地变量,这两个指针指向MEX函数的输入和输出数组。
mwPointer x_ptr, y_ptr
然后,声明数组的特征,包括行列数及大小。
mwPointer mrows, ncols
mwSize size
声明用于计算程序的变量,实际的计算程序中有哪些变量,就声明哪些变量,变量类型与实际的计算程序中一致。
real*8 x_input, y_output
描述
读取输入参数,获取输入参数的结构,
x_ptr = mxGetDoubles(prhs(1))
在Matlab里数据都是以数组的形式存在的,mxGetDoubles的作用就是把通过prhs[1]传递进来的mxArray类型的指针指向的数据赋给fortran程序里的变量。
但是,还有个问题,如果输入的不是单个的数据,而是向量或矩阵,那该怎么处理呢?通过mxGetPr只能得到指向这个矩阵的指针,如果我们不知道这个矩阵的确切大小,就没法对它进行计算。为了解决这个问题,Matlab提供了两个函数mxGetM和mxGetN来获得传进来参数的行数和列数。
mrows = mxGetM(prhs(1))
ncols = mxGetN(prhs(1))
size = mrows*ncols
将使用MEX文件时MATLAB的输入数据通过指针数组传递为fortran中的数组
call mxCopyPtrToReal8(x_ptr,x_input,size)
准备输出参数。mxCreateDoubleMatrix生成一个指针指向m×n大小的mxArray。
输入数据是在函数调用之前已经在Matlab里申请了内存的,由于mex函数与Matlab共用同一个地址空间,因而在prhs[]里传递指针就可以达到参数传递的目的。但是,输出参数却需要在mex函数内申请到内存空间,才能将指针放在plhs[]中传递出去。由于返回指针类型必须是mxArray,所以Matlab专门提供了一个函数:mxCreateDoubleMatrix来实现内存的申请。
plhs(1) = mxCreateDoubleMatrix(mrows,ncols,0)
y_ptr = mxGetDoubles(plhs(1))
至此,MATLAB使用MEX文件时输入的数据已经传递为fortran程序中所需要的输入数据,可以进行fortran程序的运算了。
执行计算
call timestwo(y_output, x_input)
将计算结果传递给MATLAB输出数组的指针。
call mxCopyReal8ToPtr(y_output,y_ptr,size)
结束
return
end
实际的计算程序
subroutine timestwo(y_output, x_input)
real*8 x_input, y_output
y_output = 2.0 * x_input
return
end
使用
编写完 .F 文件后,在 .F 文件所在目录下,MATLAB命令行窗口中对 .F 文件进行编译,命令为
mex timestwo.F
编译完成后,所在文件夹中会出现 timestwo.mexw64文件,这个文件就是二进制的MEX文件。在文件下下,运行命令
timestwo(2)
可以得到
ans =
4
说明MEX文件成功。
MATLAB的示例:timestwo.F
#include "fintrf.h"
C===============================================
#if 0
C
C timestwo.F
C .F file needs to be preprocessed to generate .for
equivalent
C
#endif
C timestwo.f
C Computational function that takes a scalar and doubles it.
C This is a MEX-file for MATLAB.
C Copyright 1984-2011 The MathWorks, Inc.
C=====================================================
C Gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C Declarations
implicit none
C mexFunction arguments:
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxGetPr
mwPointer mxCreateDoubleMatrix
integer mxIsNumeric
mwPointer mxGetM, mxGetN
C Pointers to input/output mxArrays:
mwPointer x_ptr, y_ptr
C Array information:
mwPointer mrows, ncols
mwSize size
C Arguments for computational routine:
real*8 x_input, y_output
C-----------------------------------------------------------------------
C Check for proper number of arguments.
if(nrhs .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:timestwo:nInput',
+ 'One input required.')
elseif(nlhs .gt. 1) then
call mexErrMsgIdAndTxt
('MATLAB:timestwo:nOutput',
+ 'Too many output
arguments.')
endif
C Validate inputs
C Check that the input is a number.
if(mxIsNumeric(prhs(1)) .eq. 0) then
call mexErrMsgIdAndTxt
('MATLAB:timestwo:NonNumeric',
+ 'Input must be a number.')
endif
C Get the size of the input array.
mrows = mxGetM(prhs(1))
ncols = mxGetN(prhs(1))
size = mrows*ncols
C Create Fortran array from the input argument.
x_ptr = mxGetPr(prhs(1))
call mxCopyPtrToReal8(x_ptr,x_input,size)
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(mrows,ncols,0)
y_ptr = mxGetPr(plhs(1))
C Call the computational subroutine.
call timestwo(y_output, x_input)
C Load the data into y_ptr, which is the output to
MATLAB.
call mxCopyReal8ToPtr(y_output,y_ptr,size)
return
end
C-----------------------------------------------------------------------
C Computational routine
subroutine timestwo(y_output, x_input)
real*8 x_input, y_output
y_output = 2.0 * x_input
return
end
最后
以上就是畅快大象为你收集整理的MATLAB Fortran 混合编程 timestwo.F示例的全部内容,希望文章能够帮你解决MATLAB Fortran 混合编程 timestwo.F示例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复