Search code examples
matlabfortranmex

Trying to return array from Fortran to Matlab with mex, getting empty array instead


So, I'm trying to return a an array of numbers from 1-n.

#include "fintrf.h"

C     Gateway routine
      subroutine mexFunction(nlhs, plhs, nrhs, prhs)

C     Declarations
      implicit none

C     mexFunction arguments:
      mwPointer plhs(*), prhs(*)
      integer nlhs, nrhs


      mwPointer mxGetPr
      mwPointer mxCreateDoubleMatrix
      mwPointer mxGetM, mxGetN
      mwPointer mrows, ncols
      mwSize size
      mwPointer x_ptr, y_ptr
      integer  x_input,i
      real*8, allocatable :: vec(:)
      x_ptr = mxGetPr(prhs(1))
      mrows = mxGetM(prhs(1))
      ncols = mxGetN(prhs(1))
      size = mrows*ncols

      x_ptr=mxGetPr(prhs(1))
      call mxCopyPtrToReal8(x_ptr,x_input,size)

      allocate (vec(x_input))

      do i=1,x_input
        vec(i)=i
      end do

      plhs(1) = mxCreateDoubleMatrix(1, x_input, 0)


      y_ptr = mxGetPr(plhs(1))
      call mxCopyReal8ToPtr(vec,y_ptr,x_input)



      deallocate ( vec )
      return
      end

I then call the mex file in fortran here

mex testingvec.F
Building with 'gfortran'.
MEX completed successfully.
a=testingvec(10);

and then find

a=[]

Can someone give me some help on this? If someone can give me some example code how to return a matrix as well, that would be sweet.

Thanks guys.

edit: new installment of the code. Still trying to get some help.

#include "fintrf.h"

C     Gateway routine
      subroutine mexFunction(nlhs, plhs, nrhs, prhs)

C     Declarations
      implicit none

C     mexFunction arguments:
      mwPointer plhs(*), prhs(*)
      integer nlhs, nrhs


      mwPointer mxGetPr
      mwPointer mxCreateDoubleMatrix
      mwPointer mxGetM, mxGetN
      mwPointer mrows, ncols
      mwSize size
      mwPointer x_ptr, y_ptr
      integer  i
      mwSize sizeone, x_input 
      integer*4 izero 
      real*8, allocatable :: vec(:)
      x_ptr = mxGetPr(prhs(1))
      mrows = mxGetM(prhs(1))
      ncols = mxGetN(prhs(1))
      size = mrows*ncols
      sizeone=1 
      izero=0 

      x_ptr=mxGetPr(prhs(1))
      call mxCopyPtrToReal8(x_ptr,x_input,size)

      allocate (vec(x_input))

      do i=1,x_input
        vec(i)=i
      end do

      plhs(1) = mxCreateDoubleMatrix(sizeone,x_input,izero)



      call mxCopyReal8ToPtr(vec,mxGetPr(plhs(1)),x_input)



      deallocate ( vec )
      return
      end

Solution

  • There were both declaration problems and issues with calls to mex functions. Here's a solution, which assumes that the input is an integer-valued double giving you the length of the output vector (assuming that this is what you wanted).

    #include "fintrf.h"
    
    C     Gateway routine
          subroutine mexFunction(nlhs, plhs, nrhs, prhs)
    
    C     Declarations
          implicit none
    
    C     mexFunction arguments:
          mwPointer plhs(*), prhs(*)
          integer*4 nlhs, nrhs
    
    
          mwPointer mxGetPr
          mwPointer mxCreateDoubleMatrix
          mwSize mxGetM, mxGetN
          mwSignedIndex mrows, ncols
          mwSize size, x_input, sizeone
          mwPointer x_ptr, y_ptr
          integer*4  i, izero, x_int
          real*8, allocatable :: vec(:)
          real*8 :: x_dbl
    
          sizeone = 1
          izero = 0
    
    
    
          !check input/output syntax
          if (nrhs /= 1) then
            call mexErrMsgIdAndTxt("MATLAB:testingvec:rhs",
        >            "Exactly 1 input variable required.")
          end if
          if (nlhs /= 1) then
            call mexErrMsgIdAndTxt("MATLAB:testingvec:lhs",
     >            "Exactly 1 output matrix required.")
          end if
    
    
          x_ptr = mxGetPr(prhs(1))
          mrows = mxGetM(prhs(1))
          ncols = mxGetN(prhs(1))
          size = mrows*ncols
    
          call mxCopyPtrToReal8(x_ptr,x_dbl,sizeone)
          x_input = int(x_dbl)
    
          allocate (vec(x_input))
    
          do i=1,x_input
            vec(i)=i
          end do
    
          plhs(1) = mxCreateDoubleMatrix(sizeone, x_input, izero)
    
          y_ptr = mxGetPr(plhs(1))
          call mxCopyReal8ToPtr(vec,y_ptr,x_input)
    
    
    
          deallocate ( vec )
          return
          end
    

    I introduced a check for the number of input/output variables (to be updated in the actual program). And I introduced an auxiliary x_dbl which might or might not be necessary. This version reads the double input given to your function, and truncates it to get x_input.