我是靠谱客的博主 畅快大象,最近开发中收集的这篇文章主要介绍MATLAB Fortran 混合编程 timestwo.F示例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

学习笔记。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示例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部