MATLAB,mex文件,Fortran,警告和错误

时间:2015-01-20 15:36:28

标签: matlab fortran mex

我没有完全看到我遇到的问题,而且我已尝试过我在其他论坛帖子中看到过的建议。我正在尝试根据我老板的要求写一个(fortran)mex文件。但是,在将矩阵传递给我的计算例程时,我收到了警告。如果我忽略了警告,我的MATLAB就会关闭。所以现在我尝试一个更简单的程序,一个内在的产品。但是,我仍然收到警告:"预计在(1)"其中(1)是在调用innerProd(x,y,c)'在x下面。我不确定这意味着什么......我已经包含了我的代码。

#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

我刚刚第一次学习这个,我很感激任何建议。即使它在哪里寻找解决方案。我已经在线浏览了MATLAB mex Fortran aids。那里没有任何帮助。我无法运行该函数,因此我无法使用print语句,这是一种很好的调试方法。我认为mex有打印功能,我会尽力让它起作用。

谢谢!

2 个答案:

答案 0 :(得分:2)

主要问题是你没有在任何地方将innerProd的参数声明为数组。这适用于子例程x中的实际参数ymexFunction以及虚拟参数x和{ {1}}本身{1}}。

因此,y innerProd表达式innerProd并未引用x(i)数组i的{​​{1}}个元素,但{ {1}}带有参数real*8函数 x的结果。由于您通过的real*8不是函数(过程),因此这是一个错误。

有很多方法可以解决这个问题,但所有方法都涉及将伪参数声明为数组。这提出了另一点。

你有x

i

其中未定义x。至关重要的是,从innerProd开始,您希望编译器知道integer:: i,m do i=1,m temp=temp+x(i)*y(i) end do 是数组mmexfunction的大小:这不是真的。 mx的本地变量。相反,您可能希望将其作为参数传递给子例程,并使用它来标注数组:

y

[当然,你可以使用假定形状的数组(以及m内在数据),但这是一个需要更多实质性更改的额外复杂因素。]你也可以需要考虑如何在innerProd中适当地声明数组,注意对subroutine innerProd(x,y,c,m) implicit none integer :: m real*8:: x(m),y(m),temp,c ... end subroutine 的调用也需要数组参数。

答案 1 :(得分:-1)

我无法让Fortran代码适用于innerProd,但我确实得到了C代码。如果你遇到Fortran问题,我建议使用C.看来matlab在mex文件和C语言方面更灵活。以下是代码:

#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);

}

但我仍然会对上面的Fortran代码提出建议。我想知道如何让它发挥作用。谢谢!