MATLAB, mex files, Fortran, warnings and errors

醉酒当歌 提交于 2019-12-13 04:52:47

问题


I'm not quite seeing the issue I'm having, and I've tried suggestions I've seen in other forum posts. I am trying to write a (fortran) mex file, per request of my boss. However, I was getting warnings when passing a matrix to my computational routine. If I ignored the warning, my MATLAB shut down. So now I'm trying a simpler program, an inner product. However, I am still getting the warning: "Expected a procedure at (1)" where (1) is at 'call innerProd(x,y,c)' underneath the x. I'm not sure what that means... I've included my code.

#include "fintrf.h"
C======================================================================
#if 0      
C
C     innerProd.F
C     .F file needs to be preprocessed to generate .for equivalent
C     
#endif 
C
C     innerProd.F
C     calculates the inner product

C     This is a MEX file for MATLAB.
C     Copyright 1984-2011 The MathWorks, Inc.
C     $Revision: 1.12.2.9 $

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:: mxCreateDoubleMatrix, mxGetPr,mxGetM, mxGetData
      integer:: mxIsNumeric

C     Pointers to input/output mxArrays:   
      mwPointer:: x_ptr, y_ptr, c_ptr 

C     Array information:
     mwSize:: m

C     Arguments for computational routine:      
      real*8::  x,y,c

C----------------------------------------------------------------------
C     Check for proper number of arguments. 
      if (nrhs .ne. 2) then
         call mexErrMsgTxt('Error.')
      elseif (nlhs .ne. 1) then
         call mexErrMsgTxt('One output required.')
      endif

C     Check to see if inputs are numeric.
      if (mxIsNumeric(prhs(1)) .ne. 1 ) then
         call mexErrMsgTxt('Input # 1 is not a numeric array.')
      elseif (mxIsNumeric(prhs(2)) .ne. 1) then
         call mexErrMsgTxt('Input #2 is not a numeric array.')
      endif

C     Find dimensions of mxArrays
      m=mxGetM(prhs(1))

C     create Fortran arrays from the input arguments      
      x_ptr=mxGetData(prhs(1))
      call mxCopyPtrToReal8(x_ptr,x,m)
      y_ptr= mxGetData(prhs(2))   
      call mxCopyPtrToReal8(y_ptr,y,m)

C     create matrix for the return argument
     plhs(1) =mxCreateDoubleMatrix(1,1,0)      
     c_ptr= mxGetPr(plhs(1))

C     Call the computational subroutine.
     call innerProd(x,y,c)

C     Load the output into a MATLAB array.
     call mxCopyReal8ToPtr(c, c_ptr, 1)

     return
     end subroutine mexFunction

C----------------------------------------------------------------------
C     Computational routine
      subroutine innerProd(x,y,c)
      implicit none

  real*8:: x,y,temp,c
  integer:: i,m

  do i=1,m
  temp=temp+x(i)*y(i)
  end do

  c = temp
  return
  end subroutine innerProd

I'm just learning this for the first time, and I would appreciate any suggestions. Even if it is where to look for solutions. I've looked through MATLAB mex Fortran aids online. There isn't any help there. I can't get the function to run, so I can't use print statements which is a good way to debug. I think mex has a print function, I will try to get that to work.

Thank you!


回答1:


The main problem is that you haven't anywhere declared the arguments of innerProd as arrays. That holds for the actual arguments x and y in the subroutine mexFunction and the dummy arguments x and y in innerProd itself.

So, in innerProd the expression x(i) isn't referencing the i-th element of the real*8 array x, but the real*8 result of the function x with argument i. As the x you've passed isn't a function (procedure), this is an error.

There are ways to solve this, but all involve declaring the dummy arguments as arrays. Which brings up another point.

You have in innerProd

integer:: i,m

do i=1,m
  temp=temp+x(i)*y(i)
end do

where m is not defined. Crucially, from mexfunction you're expecting the compiler to know that m is the size of the arrays x and y: this isn't true. m is a variable local to innerProd. Instead you may want to pass it as an argument to the subroutine and use that to dimension the arrays:

subroutine innerProd(x,y,c,m)
  implicit none

  integer :: m
  real*8:: x(m),y(m),temp,c
  ...
end subroutine

[You could, of course, use assumed-shape arrays (and the SIZE intrinsic), but that's an additional complication requiring more substantial changes.] You also need to think about how to declare arrays appropriately in mexfunction, noting that the call to mxCopyPtrToReal8 also requires an array argument.




回答2:


I couldn't get the Fortran code to work for innerProd, but I did get C code to work. I recommend, if you are having issues with Fortran, to use C. It seems that Matlab is more flexible when it comes to mex files and C. Here is the code:

#include "mex.h"

/*
* innerProd.c
*
*Computational function that takes the inner product of two vectors.
*
*Mex-file for MATLAB.
*/

void innerProd(double *x, double *y,double *c,int m){
 double temp;
 int i;

for(i=0; i < m; i++){
temp = temp + x[i]*y[i];
}

*c=temp;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *x, *y, *c;
size_t m;

/*check for proper number of arguments.*/
if(nrhs != 2){
mexErrMsgIdAndTxt("MATLAB:innerProd:invalidNumInputs","Two input required.");
}

/*The input must be a noncomplex double vector.*/
m = mxGetM(prhs[0]);
if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || m==1){
mexErrMsgIdAndTxt("MATLAB:innerProd:inputNotRealDouble","Input must be noncomplex double vector");
}

/*create return argument */
plhs[0] = mxCreateDoubleMatrix(1,1,0);
c=mxGetPr(plhs[0]);

/*Assign pointers to each input and output. */
x = mxGetPr(prhs[0]);
y=mxGetPr(prhs[1]);

/*call subroutine*/
innerProd(x,y,c,m);

}

I will still take suggestions on the Fortran code above, though. I'd like to know how to get it to work. Thanks!



来源:https://stackoverflow.com/questions/28049298/matlab-mex-files-fortran-warnings-and-errors

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!