****The mex file with a different prhs****

Hi, I have a compiled mex file that gives rubbish results.
After some detective work, I realised that the computational subroutine worked fine and that the problem was with the prhs. Strangely, the prhs did not correspond to my input.
I think it has most probably got to do with the type (int32 or int64), although I'm can't be absolutely sure. Does anybody know why it happened?
>> mex Print.F
>> Print(1,3)
ans =
4613937818241073152
-------------------------------------------------------------------------
#include "fintrf.h"
C======================================================================
#if 0
C
C add.F
C .F file needs to be preprocessed to generate .for equivalent
C
#endif
C
C add.f
C
C Adds two integers
C
C======================================================================
C *Gateway routine*
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C *Declarations*
implicit none
C *mexFunction arguments:*
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C *Declare local variables for the mexfunction arguments*
mwPointer a, b
mwPointer c
mwSize mrows, ncols
mwSize size
mwSize :: one = 1
integer*4 classid
integer*4 :: mxREAL = 0
integer*4 mxIsInt64
C *Declare the symbolic names and types of this function*
integer mxIsNumeric
integer*4 mxClassIDFromClassName
mwPointer mxGetNumberOfElements
mwPointer mxCreateNumericMatrix
mwPointer mxGetData, mxGetPr, mxCreateDoubleMatrix
mwSize mxGetM, mxGetN
C *Verify MEX-File Input and Output Arguments*
if( nrhs /= 2 .or. nlhs > 1 ) then
call mexErrMsgTxt('Need 2 inputs and at most 1 output')
endif
if( mxGetNumberOfElements(prhs(1)) /= 1 .or.
+ mxGetNumberOfElements(prhs(2)) /= 1 ) then
call mexErrMsgTxt('Inputs must be scalar')
endif
C *Prepare in/out matrix:*
classid = mxClassIDFromClassName("int64")
plhs(1) = mxCreateNumericMatrix(one,one,classid,mxREAL)
a = mxGetPr(prhs(1))
b = mxGetPr(prhs(2))
c = mxGetPr(plhs(1))
C *Get the size of the input array.*
c mrows = mxGetM(prhs(1))
c ncols = mxGetN(prhs(1))
c size = mrows*ncols
C *Call the computational subroutine.*
call add(%val(a), %val(b), %val(c))
return
end
C-----------------------------------------------------------------------
C *Computational subroutine*
subroutine add(a, b, c)
integer*8 a, b, c
c = b
return
end

 Accepted Answer

Hi,
it's not the data into the mex function (they are of type double, that's fine), but it's the plhs you have wrong: you create a numeric matrix of type int64, therefore you can't use mxGetPr but need to use mxGetData. And if you want to call your function with int64 you need to do explicitly, i.e.
Print(int64(1), int64(3))
Titus

6 Comments

Thanks! But may I know why do I have to explicitly tell Matlab that my arguments are int64(1) and int64(3)? This is because, the other sample functions like timestwo.F do not require me to do so?
Because you used integer*8 for the a, b, c variable types in your subroutine add. If you had used real*8 then the routine would have taken double inputs. If you had used real*4 then the routine would have taken single inputs. If you had used integer*4 then the routine would have taken int32 inputs. Etc, etc. If you want the routine to take any class of input, then you will have to add code to handle all of the different types of inputs.
Zhong Hao
Zhong Hao on 5 Jun 2014
Edited: Zhong Hao on 5 Jun 2014
Why then does timestwo.F not require me to explicitly indicate the type during execution even when no 'special' code was added?
Because timestwo.F is a poorly written mex routine. Here are the problems with this example:
1) Does not check inputs properly.
It should be checking that the input is double class, but it doesn't. It only checks to see if the input is numeric. This is insufficient. If you pass timestwo an int64 class variable you will get a wrong garbage result. If you pass timestwo a single class variable it will likely crash MATLAB since it will access invalid memory.
2) Does not work with arrays properly.
The code at first glance looks like it will handle arrays because of all the m & n stuff you see, and it will create a matrix output, but only the first element will get multiplied by 2 because the timestwo Fortran subroutine only works with scalars (it is using an implicit interface). In fact, if you pass timestwo anything other than a scalar it will likely crash MATLAB because it will access invalid memory (try to copy multiple values to the address of x and y, which are only scalars).
3) It uses "size" as a variable name
This is unwise because size is the name of a Fortran intrinsic function.
4) It declares the wrong type for the size variables
integer m, n, size
These variables should be mwSize, not integer. If you try this code on a 64-bit system where mwSize (the type that the API routines are expecting for arguments) is a 64-bit integer, the code will likely crash MATLAB because it will access invalid memory (default integer is likely 32-bit, even on a 64-bit system).
5) It uses a constant literal in one of the API calls:
plhs(1) = mxCreateDoubleMatrix(m,n,0)
This error is likely benign, but if a default integer happens to be 64-bit you will have a type mismatch because the last argument is supposed to be a 32-bit integer. Having pointed it out, this error is likely benign since the bit pattern is all 0-bits anyway, and you have enough of them in either case at that address, so it probably won't cause any problems. Still, it is bad programming practice. You should never use any literal constants in the calls to the API functions. Always use variables that match the signature exactly.
Hey James, thanks for your help.
Are there any good and instructive example codes that show how to use a fortran gateway correctly?
Thank you once again.
Go ahead and look through the MATLAB provided examples, but keep in mind they are not all written properly. You might also look at this FEX submission for a Fortran 95 interface (although I don't think it has been entirely updated for 64-bit systems yet):

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!