MATLAB® Gateways on Linux using the NAGWare f95 Compiler
The Mathworks recommends using g77 as the Fortran compiler for generating MATLAB® MEX files on Linux. However, the NAGWare f95 Compiler may also be used as the Fortran compiler. Indeed there is some advantage to using NAGWare f95 rather than g77 as pointers and dynamic allocation of memory are available as part of the Fortran 95 language.
Dynamic Allocation of Memory using Fortran 95
The Fortran 95 language allows you to declare allocatable arrays which can be dimensioned at run time. If you are only working on platforms where a Fortran 95 compiler compatible with MATLAB is available, this might be the way you choose to allocate dynamically memory for temporary workspace arrays.
Dynamic Memory Allocation using the MATLAB API
The documented way to get dynamic allocation of memory is to use the MATLAB API to create a MATLAB array and store the pointer to this memory in an INTEGER variable which is passed out to another routine by value. The corresponding dummy argument in the receiving routine is declared to be an array of the correct length and data type.
Another common practice is to allocate memory using the MATLAB memory manager (mxCalloc) and pass this to another Fortran routine by value to create temporary arrays for copying, for example, integers to and from MATLAB arrays.
The g77 compiler does have the %VAL construct and this is the method used.
In Fortran 95 you can declare a pointer which can then be passed to another Fortran routine that is expecting an array argument. This means that the %VAL construct is not needed. Note, though, that the compiler may generate warnings because of the mismatch in type and attributes between actual and dummy arguments.
On Linux, the NAGWare f95 Compiler may be used to generate MEX files that make full use of dynamic allocation of memory. But, note that the "-mismatch_all" option must be specified to downgrade the argument type mismatch error to a warning.
Example of Dynamic Allocation of Memory using NAGWare f95
The code shown below is the example from page 33 of the MATLAB 5 Application Program Interface Guide reworked to use Fortran 95 pointers to store the address of memory allocated by mxGetPr.
The changes to the standard example are marked in the code with comments.
- An interface block has been added to describe mxGetPr as an integer pointer function. Fortran 95 does not have generic pointers, so we just pretend that this pointer is always to integer type. Even if this is not true, it does not matter as the pointer is simply passed out to dbl_mat and is never dereferenced in mexfunction.
- The variables pr_in and pr_out are declared as integer pointers.
- Use pointer assignment for pr_in and pr_out.
- The variables pr_in and pr_out are passed as actual arguments to dbl_mat.
Here is the full code for the example.
subroutine mexfunction(nlhs, plhs, nrhs, prhs) integer nlhs, nrhs integer plhs(*), prhs(*) ! New interface block for pointer function mxGetPr. interface function mxgetpr(pm) integer,pointer :: mxgetpr integer :: pm end function mxgetpr end interface integer m_in, n_in ! New declaration for the pointers. integer, pointer :: pr_in, pr_out m_in = mxGetM(prhs(1)) n_in = mxGetN(prhs(1)) ! Use pointer assignment pr_in => mxgetpr(prhs(1)) plhs(1) = mxcreatefull(m_in,n_in,0) ! Use pointer assignment pr_out => mxgetpr(plhs(1)) ! pass pr_in and pr_out straight to dbl_mat call dbl_mat(pr_out,pr_in,m_in,n_in) end subroutine dbl_mat(out_mat,in_mat,m,n) integer m, n double precision out_mat(m,n), in_mat(m,n) ! We don't need DO loops in Fortran 95! out_mat = 2*in_mat end
Changes to mexopts.sh to use NAGWare f95
In the file "mexopts.sh", comment out the g77 definitions and add the definitions for NAGWare f95 shown below.
MATLAB 6 with NAGWare f95 Release 4.1 or later
FC='f95' FFLAGS='-Wc,-fPIC -mismatch_all -dcfuns -w=all' FLIBS='/usr/local/lib/f95/quickfit.o /usr/local/lib/f95/libf96.a' LD='gcc'
This method produces smaller MEX files.
FC='f95' FFLAGS='-Wc,-fPIC -mismatch_all -dcfuns -w=all' FLIBS='' LD="$COMPILER" NWF95='-ldarg -Wl,-export-dynamic' TMWFLAGS="-Wl,-shared -ldarg -Wl,--version-script,$TMW_ROOT/extern /lib/$Arch/$MAPFILE" LDFLAGS="$NWF95 $TMWFLAGS"Note, the -ldarg option is equivalent to "-Wl," but allows commas in its argument.