Reputation: 25
I'm writing a simple MEX file for a Matlab/Fortran interface. The code is compiling, however, the integer number n (e.g., 5) is passing as a huge number (O(14)). When n is integer*4 it passes as 0.
The user runs the compiled mex file as [z,w] = smmat(c,e,eps,n), where c is a complex matrix of size 20xnl, e is a real matrix of size 8xnl, eps is a real matrix of size 5xnl, n in a integer scalar. z is an output complex matrix and w should be an output real matrix.
Can someone provide their expertise? Thanks :) Here is the code:
#include "fintrf.h"
C Gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C Declarations
implicit none
C mexFunction arguments: plhs - left (output) pointers of unknown (*) size
C prhs - right (input) pointers of unknown (*) size
C nlhs - number (integer) of left (output) arguments
C nrhs - number (integer) of right (input) arguments
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxGetPr, mxGetPi
mwPointer mxCreateDoubleMatrix
mwPointer mxGetM, mxGetN
integer mxIsComplex, mexEvalString
C Array information:
mwPointer mc, nc, me, ne, mep, nep, mn, nn, nz, nw, elc, ele, elep
integer*8 n
real*8 e(80), eps(50), w(5000000)
complex*16 c(200), z(5000000)
C-----------------------------------------------------------------------
C Check for proper number of arguments.
if (nrhs .ne. 4) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nInput',
+ 'Four inputs required.')
elseif (nlhs .gt. 2) then
call mexErrMsgIdAndTxt ('MATLAB:convec:nOutput',
+ 'Too many output arguments.')
endif
C Validate inputs
mc = mxGetM(prhs(1))
nc = mxGetN(prhs(1))
me = mxGetM(prhs(2))
ne = mxGetN(prhs(2))
mep = mxGetM(prhs(3))
nep = mxGetN(prhs(3))
mn = mxGetM(prhs(4))
nn = mxGetN(prhs(4))
C Size of inputs
elc = mc*nc
ele = me*ne
elep = mep*nep
C Check number of lines of cij, eij, epsij
if(mc .ne. 20 .or. me .ne. 8 .or. mep .ne. 5) then
call mexErrMsgIdAndTxt ('Matlab:smmat:NotEnoConst',
+ 'Inputs must have correct number of constants.')
C Check that inputs are scalar.
elseif(mn .ne. 1 .or. nn .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:NonScalar',
+ 'Inputs must be a scalar.')
C Check size of the inputs.
elseif(elc .gt. 200 .or. ele .gt. 80 .or. elep .gt. 50) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nLayer',
+ 'Maximum number of layers is 10.')
C Check if cij is complex.
elseif(mxIsComplex(prhs(1)) .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:NonComplex',
+ 'Cij must be complex.')
C Check if number of layers is correct for every constant.
elseif(nc .ne. ne .or. nc .ne. nep .or. ne .ne. nep) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nLayer',
+ 'Number of layers of constants must be equal.')
endif
C Create the output array.
nz = mc*me
nw = mc*mep
plhs(1) = mxCreateDoubleMatrix(mc, me, 1)
plhs(2) = mxCreateDoubleMatrix(mc, mep, 0)
C Load the data into Fortran arrays(native COMPLEX data).
call mxCopyPtrToComplex16(mxGetPr(prhs(1)),
+ mxGetPi(prhs(1)),c,elc)
call mxCopyPtrToReal8(mxGetPr(prhs(2)),e,ele)
call mxCopyPtrToReal8(mxGetPr(prhs(3)),eps,elep)
call mxCopyPtrToInteger4(mxGetPr(prhs(4)),n,1)
C Call the computational subroutine.
call smmat(c,e,eps,n,z,w,mc,me,mep,nc)
C Load the output into a MATLAB array.
call mxCopyComplex16ToPtr(z,mxGetPr(plhs(1)),
+ mxGetPi(plhs(1)),nz)
call mxCopyReal8ToPtr(w,mxGetPr(plhs(2)),nw)
return
end
C-----------------------------------------------------------------------
C Computational subroutine
subroutine smmat(c,e,eps,n,z,w,mc,me,mep)
implicit none
integer*8 n
real*8 e(8,*), eps(5,*), w(mc,mep)
complex*16 c(20,*), z(mc,me)
mwSize mc, nc, me, mep, i, j
C Determine size of stiff and mass matrices
C Initialize the output arrays
w = 0.0_8
do 20 i=1,mc
do 10 j=1,me
z(i,j) = (0.0,0.0)
10 continue
20 continue
do 40 i=1,mc
do 30 j=1,me
z(i,j) = z(i,j) + e(j,1) * c(i,1)
30 continue
40 continue
do 60 i=1,mc
do 50 j=1,mep
w(i,j) = w(i,j) + real(n)
50 continue
60 continue
return
end
C-----------------------------------------------------------------------
Upvotes: 1
Views: 241
Reputation: 60494
When you type
n=5;
smmat(c,e,eps,n)
in MATLAB, n
is a double, even though it has an integer value. In your MEX-file, you need to read it as a double. You cannot interpret the mxArray
data as whatever type is convenient. Always use functions such as mxIsDouble
to verify the type of the array before you read the data from it.
If you expect an integer value, you should probably still read it as double, and then cast to integer.
Upvotes: 1