Problems with Fortran MEX files with R2020b on Linux
조회 수: 2 (최근 30일)
이전 댓글 표시
Hello,
I wanted to try out using Fortran MEX files with Matlab R2020b on Linux (Ubuntu 20.04).
First, "mex -setup" does not detect the right compiler. On my system, I have installed both -
gfortran 9.3.0 as well as gfortran 8.4.0.
According to the list of supported compilers, R2020b supports gfortran 8.x - but
mex -setup
does not detect it.
So how can tell mex to properly use gfortran 8.4 ?
When I compile e.g. the supplied example timestwo.F, I get weird behaviour. It compiles without error, but the output values are totally wrong. E.g.
timestwo([1 2 3 4 5])
gives
ans =
2.0000 0.0000 5.0000 0.0000 0.0000
For me, this looks like a memory access problem on input or output parameters. And timestwo(1:10) crashes.
I have tried with switch -R2017a (separate complex API) as well as -R2018a (interleaved complex API), but without success and same errors.
Any ideas, what is going wrong here ?
Best regards,
Denn
댓글 수: 0
채택된 답변
James Tursa
2021년 2월 15일
So, the timestwo.F file that ships with MATLAB has bugs. I pointed this out to TMW several years ago, but I just checked and as of R2020a the bugs are still there. Yes this code will crash or behave badly if you give it anything other than a full double scalar. E.g., take these lines:
real*8 x_input, y_output
mrows = mxGetM(prhs(1))
ncols = mxGetN(prhs(1))
size = mrows*ncols
#if MX_HAS_INTERLEAVED_COMPLEX
x_ptr = mxGetDoubles(prhs(1))
#else
x_ptr = mxGetPr(prhs(1))
#endif
call mxCopyPtrToReal8(x_ptr,x_input,size)
So x_input and y_output are scalars, but the mxCopyPtrToReal8( ) call happily will try to copy any size array into them. If the input is anything other than a scalar you will be writing into invalid memory and bad things happen. Also there are no checks for sparsity or non-double numeric.
Here is one way to write the routine without these bugs (CAVEAT: I don't have a Fortran compiler installed so this is all untested):
#include "fintrf.h"
!\
! Gateway
!/
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
implicit none
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
!\
! API functions
!/
mwPointer, external :: mxGetData
mwPointer, external :: mxDuplicateArray
integer*4, external :: mxIsDouble, mxIsComplex, mxIsSparse
mwPointer, external :: mxGetNumberOfElements
!\
! Data pointer
!/
mwPointer y_ptr
!\
! Array size
!/
mwPointer n
!-----
!\
! Argument checks
!/
if( nrhs /= 1 ) then
call mexErrMsgIdAndTxt ('MATLAB:timestwo:nInput', &
& 'One input required.')
elseif( nlhs > 1 ) then
call mexErrMsgIdAndTxt ('MATLAB:timestwo:nOutput', &
& 'Too many output arguments.')
elseif( mxIsDouble(prhs(1))==0 .or. &
& mxIsComplex(prhs(1))==1 .or. &
& mxIsSparse(prhs(1))==1 ) then
call mexErrMsgIdAndTxt ('MATLAB:timestwo:InvalidInput', &
& 'Input must be full real double.')
endif
!\
! Get array size
!/
n = mxGetNumberOfElements(prhs(1))
!\
! Create output array as a deep data copy of the input
!/
plhs(1) = mxDuplicateArray(prhs(1))
!\
! Get the data pointer
!/
y_ptr = mxGetData(plhs(1))
!\
! Call the Multiply routine, passing address by value
!/
if( n > 0 ) call timestwo( %VAL(y_ptr), n )
!\
! Done
!/
return
end
!\
! The Multiply routine -------------------------------------------------
!/
subroutine timestwo(y_output, n)
mwPointer n
real*8 y_output(n)
y_output = 2.0 * y_output
return
end
The reason for the two & usage on lines is so that the code can be compiled as either fixed format .f or free format .f90 and the continuation characters will work in either case.
댓글 수: 2
Josh G.
2021년 5월 24일
편집: Josh G.
2021년 5월 24일
@Delta-Echo N.N. Matlab uses whatever is stored in the $FC environment variable as the Fortran compiler, so you can change the version by setting the environment variable when you call mex: mex FC=$path_to_your_gfortran_version_here timestwo.F
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 MATLAB Compiler에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!