问题
I am toying with matlab, mex, intel fortran in visual studio etc. I copied a routine from here doing the multiplication of a matrix by a scalar :
C Computational subroutine
subroutine xtimesy(x, y, z, m, n)
real*8 x, y(3,3), z(3,3)
integer m, n
do 20 i=1,m
do 10 j=1,n
z(i,j) = x*y(i,j)
10 continue
20 continue
return
end
The initial wrapping code supposed to produce the mexw64 file was crashing on the elseif (mxIsNumeric(prhs(2)) .ne. 1) then
so that I have adapted it as follows :
#include <fintrf.h>
C The gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
mwPointer mxGetM, mxGetN, mxIsNumeric
mwPointer mxCreateDoubleMatrix
mwPointer plhs(*), prhs(*)
integer x_pr, y_pr, z_pr
integer nlhs, nrhs
integer m, n, size
real*8 x, y(3,3), z(3,3)
C Check for proper number of arguments.
if (nrhs .ne. 2) then
call mexErrMsgTxt('Two inputs required.')
elseif (nlhs .ne. 1) then
call mexErrMsgTxt('One output required.')
endif
C Check to see both inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1) then
call mexErrMsgTxt('Input #1 is not a numeric.')
elseif (mxIsNumeric(prhs(2)) .ne. 1) then
call mexErrMsgTxt('Input #2 is not a numeric array.')
endif
C Check that input #1 is a scalar.
m = mxGetM(prhs(1))
n = mxGetN(prhs(1))
if(n .ne. 1 .or. m .ne. 1) then
call mexErrMsgTxt('Input #1 is not a scalar.')
endif
C Get the size of the input matrix.
m = mxGetM(prhs(2))
n = mxGetN(prhs(2))
size = m*n
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(m, n, 0)
x_pr = mxGetPr(prhs(1))
y_pr = mxGetPr(prhs(2))
z_pr = mxGetPr(plhs(1))
C Load the data into Fortran arrays.
call mxCopyPtrToReal8(x_pr, x, 1)
call mxCopyPtrToReal8(y_pr, y, size)
C Call the computational subroutine.
call xtimesy(x, y, z, m, n)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(z, z_pr, size)
return
end
At debug in visual studio, the first and second input to my function have the right dimensions (resp 1x1 and 3x3) but prhs
is strange. Precisely, for this input in matlab :
at debug in visual studio I see :
and I find strange that the phrs
which is an array of two pointer to arrays, contains/points has "type" (1:1)
. I ran the lines before the one where the breakpoint is set, lines involving prhs(2)
and there was no mistake on them. Also, the value of prhs(1)
and prhs(2)
are strange. I suspect that somehow somewhere I filled variables with values that can be casted to integers that are too big for the types of the variables involved, but I cannot find where.
I crash if I execute the assertion of the breakpoint line, with the following message in matlab :
Error using doubleMatrixMultiplication
Requested 14757395255531667459x14757395255531667459 (17179869184.0GB) array exceeds maximum array size preference. Creation of
arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference
panel for more information.
Details : I have visual studio 2017 last update, matlab 2018b and I tried with intel visual fortran from parallel studio xe 2018 update 5 as well as 2019 update 3.
Edit. (May the 8th, 2019)
The correct code for the mex part is finally :
#include <fintrf.h>
C The gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
mwPointer mxGetM, mxGetN, mxIsNumeric
mwPointer mxCreateDoubleMatrix
mwPointer plhs(*), prhs(*)
mwPointer x_pr, y_pr, z_pr
integer nlhs, nrhs
mwSize m, n, size
real*8 x, y(3,3), z(3,3)
C Check for proper number of arguments.
if (nrhs .ne. 2) then
call mexErrMsgTxt('Two inputs required.')
elseif (nlhs .ne. 1) then
call mexErrMsgTxt('One output required.')
endif
C Check to see both inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1) then
call mexErrMsgTxt('Input #1 is not a numeric.')
elseif (mxIsNumeric(prhs(2)) .ne. 1) then
call mexErrMsgTxt('Input #2 is not a numeric array.')
endif
C Check that input #1 is a scalar.
m = mxGetM(prhs(1))
n = mxGetN(prhs(1))
if(n .ne. 1 .or. m .ne. 1) then
call mexErrMsgTxt('Input #1 is not a scalar.')
endif
C Get the size of the input matrix.
m = mxGetM(prhs(2))
n = mxGetN(prhs(2))
size = m*n
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(m, n, 0)
x_pr = mxGetPr(prhs(1))
y_pr = mxGetPr(prhs(2))
z_pr = mxGetPr(plhs(1))
C Load the data into Fortran arrays.
call mxCopyPtrToReal8(x_pr, x, 1)
call mxCopyPtrToReal8(y_pr, y, size)
C Call the computational subroutine.
call xtimesy(x, y, z, m, n)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(z, z_pr, size)
return
end
来源:https://stackoverflow.com/questions/56009962/strange-values-at-debug-for-fortran-mex-code