|
"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hkr0a3$4fn$1@fred.mathworks.com>...
> "Scott Tyler" <styler@live.com> wrote in message <hkqjdj$b53$1@fred.mathworks.com>...
> > "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hkqid4$977$1@fred.mathworks.com>...
> > > "Scott Tyler" <styler@live.com> wrote in message <hkq7nq$m3b$1@fred.mathworks.com>...
> > > > I have several Fortran subroutines, each with multiple named common blocks. I would like to call these subroutines from Matlab instead of from a main fortran routine. However, I am not sure how to generate the common block data, required by the fortran subroutines, from Matlab. Any help will be greatly appreciated.
> > > > Scott
> > >
> > > Not sure what you are asking. Are you simply asking how to populate the variables in a COMMON block with data generated on the MATLAB side? e.g., are you trying to write a mex function that passes in MATLAB variables and then calls a Fortran subroutine that takes part or all of its input from COMMON blocks? If so, I can help with that.
> > >
> > > James Tursa
> >
> >
> > Yes, that is correct. I am trying to call a fortran routine from Matlab that requires information from a COMMON block. I need to create and populate that block from Matlab.
> >
> > Scott
>
> I will offer two methods. Both of them involve copying, which can't be avoided if you want to retain the COMMON block interface. The first uses only stock MATLAB API routines. The second uses my Fortran 95 Interface routines which can be found here:
>
> http://www.mathworks.com/matlabcentral/fileexchange/25934-fortran-95-interface-to-matlab-api-with-extras
>
> Both take a 5-element double vector, multiply it by 2, and return the result.
>
> James Tursa
>
> --------------------------------------------------------------------------------------------
>
> Call the 1st file e.g. common1.f and compile it with
>
> mex common1.f
>
> Run it with
>
> common1([1 2 3 4 5])
>
> --------------------------------------------------------------------------------------------
>
> #include "fintrf.h"
>
> #ifndef mwSize
> #define mwSize integer*4
> #endif
>
> #ifndef mwPointer
> #define mwPointer integer*4
> #endif
>
> !---------------------------------------------------------------------
>
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> implicit none
> !-ARG
> mwPointer plhs(*), prhs(*)
> integer*4 nlhs, nrhs
> !-FUN
> mwPointer, external :: mxGetPr
> mwPointer, external :: mxCreateDoubleMatrix
> integer*4, external :: mxIsDouble
> mwSize, external :: mxGetNumberOfElements
> mwSize, external :: mxGetM
> mwSize, external :: mxGetN
> !-COM
> real(8) inarray(5), outarray(5)
> common /stuff/ inarray, outarray
> !-LOC
> mwSize :: m, n
> integer*4 :: mxREAL = 0
> mwPointer pr
> logical ok
> !-----
> ok = .false.
> if( nrhs == 1 ) then
> if( mxIsDouble(prhs(1)) == 1 ) then
> if( mxGetNumberOfElements(prhs(1)) == 5 ) then
> ok = .true.
> endif
> endif
> endif
> if( .not.ok ) then
> call mexErrMsgTxt("Need one 5-element double input")
> endif
> if( nlhs > 1 ) then
> call mexErrMsgTxt("Too many outputs")
> endif
> pr = mxGetPr(prhs(1))
> m = mxGetM(prhs(1))
> n = mxGetN(prhs(1))
> call mxCopyPtrToReal8(pr, inarray, m*n)
> call sub
> plhs(1) = mxCreateDoubleMatrix(m, n, mxREAL)
> pr = mxGetPr(plhs(1))
> call mxCopyReal8ToPtr(outarray, pr, m*n)
> end subroutine mexFunction
> !---------------------------------------------------------------
> subroutine sub
> implicit none
> !-COM
> real(8) inarray(5), outarray(5)
> common /stuff/ inarray, outarray
> !-----
> outarray = 2.d0 * inarray
> end subroutine sub
>
>
> --------------------------------------------------------------------------------------------
>
> Call the 2nd file e.g. common2.f and compile it with
>
> mex -c MatlabAPImex.f
> mex -c MatlabAPImx.f
> mex common2.f MatlabAPImex.obj MatlabAPImx.obj
>
> Run it with
>
> common2([1 2 3 4 5])
>
> --------------------------------------------------------------------------------------------
>
> #include "fintrf.h"
>
> #ifndef mwSize
> #define mwSize integer*4
> #endif
>
> #ifndef mwPointer
> #define mwPointer integer*4
> #endif
>
> !---------------------------------------------------------------------
>
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> use MatlabAPImex
> use MatlabAPImx
> implicit none
> !-ARG
> mwPointer plhs(*), prhs(*)
> integer*4 nlhs, nrhs
> !-COM
> real(8) inarray(5), outarray(5)
> common /stuff/ inarray, outarray
> !-LOC
> real(8), pointer :: fp(:)
> !-----
> if( nrhs /= 1 ) goto 900
> if( nlhs > 1 ) then
> call mexErrMsgTxt("Too many outputs")
> endif
> fp => fpGetPr1(prhs(1))
> if( .not.associated(fp) ) goto 900
> if( size(fp) /= 5 ) goto 900
> inarray = fp
> call sub
> plhs(1) = mxArray(outarray, orient="row")
> return
> 900 call mexErrMsgTxt("Need one 5-element double input")
> end subroutine mexFunction
> !---------------------------------------------------------------
> subroutine sub
> implicit none
> !-COM
> real(8) inarray(5), outarray(5)
> common /stuff/ inarray, outarray
> !-----
> outarray = 2.d0 * inarray
> end subroutine sub
James,
Thanks for the suggestion. This worked out well.
Scott
|