From: James Tursa on 24 Nov 2009 14:54 On Tue, 24 Nov 2009 19:01:01 +0000 (UTC), glen herrmannsfeldt <gah(a)ugcs.caltech.edu> wrote: >James Tursa <aclassyguywithaknotac(a)hotmail.com> wrote: > >> The non-standard %LOC() and %VAL() constructs are available in the >> Intel Fortran and Compaq Fortran compilers that I have (32-bit, >> WinXP). Are these constructs available in other compilers such as >> gfortran, f95, etc? What about linux, mac, etc.? If not, is there a >> workaround for this functionality? I am writing a package for others >> to use and would like it to run in other environments out of the box >> if possible. Thanks. > >These came with VAX (yes VAX, not VMS) that tried to define standard >calling conventions. They defined call by value, reference, and >descriptor. Each compiler would use the appropriate method, with >%val(), %ref(), and %descr() allowing one to override the default. >(Especially useful for interlanguage calling). > >With assumed shape arrays, Fortran needs a call by descriptor method >to pass the array information. Fortran 2003 added call by value, >possibly related to the C interoperability feature to be able >to call C routines expecting call by value. C interoperability >also adds C_LOC(), which gives a C pointer to a data item. > >Compilers with some connection to DEC, or trying to be compatible >with programs written for VAX might implement %LOC() and %VAL(). > >-- glen Thanks. What I am doing is turning separate items, a raw address and shape information, into a Fortran pointer. I know it is non standard, but it works beautifully for the target (please excuse the pun) audience, MATLAB. The supplied MATLAB functions for getting at a MATLAB variable return (in separate functions) a raw address and shape information. I discovered a way to get these separate items all packaged up into a single Fortran pointer by using a combination of explicit and implicit interface routines, but I need the %VAL( ) and %LOC( ) constructs. e.g., here is an example from my code: function fpGetPr2Double( mx ) result(fp) implicit none real(8), pointer :: fp(:,:) !-ARG mwPointer, intent(in) :: mx !-COM real(8), pointer :: Apx2(:,:) common /MatlabAPI_COMA2/ Apx2 !-LOC mwSize, parameter :: stride = 1 mwPointer :: pr mwSize, pointer :: dims(:) !----- if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. & & mxGetNumberOfDimensions(mx) == 2 ) then pr = mxGetPr( mx ) dims => fpGetDimensions( mx ) call MatlabAPI_COM_Apx2( %VAL(pr), stride, dims ) fp => Apx2 else nullify( fp ) endif return end function fpGetPr2Double !---------------------------------------------------------------------- subroutine MatlabAPI_COM_Apx2( A, stride, DIMS ) implicit none !-ARG mwSize, intent(in) :: stride, DIMS(2) real(8), target, intent(in) :: A(stride,DIMS(1),DIMS(2)) !-COM real(8), pointer :: Apx2(:,:) common /MatlabAPI_COMA2/ Apx2 !----- Apx2 => A(1,:,:) return end subroutine MatlabAPI_COM_Apx2 In the above code, mx is an address of a MATLAB variable, the mxGetPr returns the raw address of the data of the MATLAB variable, and dims will contain the dimensions of the MATLAB variable (in this case a 2D object). So I have a raw address in pr (the mwSize is just an integer(4) or integer(8) to contain the address) and the shape in separate pieces. The fpGetPr2Double routine has an explicit interface, of course. Then I call the implicit interface routine MatlabAPI_COM_Apx2 to get the raw pieces passed down and interpreted as a regular Fortran array, which can then be pointed to with a Fortran pointer. The end result up the chain is a Fortran pointer that has the correct shape of the original data. Having all of the dimensions & shape packaged in the Fortran pointer has obvious advantages in the calling routine because I can now access the raw data area just like it was a regular Fortran array. Also, a variation of this can use MATLAB memory allocation functions to allocate target memory (which gets garbage collected by the MATLAB memory manager if necessary) instead of the Fortran allocate function. And I have a reshape function that returns a pointer to the original data without copying ... an advantage one might want if working with very large arrays. This all works great, but only if the compiler supports the %VAL( ) and %LOC( ) constructs. I will look into the C_LOC function to see if that will help me. James Tursa
From: glen herrmannsfeldt on 24 Nov 2009 15:27 James Tursa <aclassyguywithaknotac(a)hotmail.com> wrote: (snip regarding %loc and %val) > Thanks. What I am doing is turning separate items, a raw address and > shape information, into a Fortran pointer. I know it is non standard, > but it works beautifully for the target (please excuse the pun) > audience, MATLAB. The supplied MATLAB functions for getting at a > MATLAB variable return (in separate functions) a raw address and shape > information. I discovered a way to get these separate items all > packaged up into a single Fortran pointer by using a combination of > explicit and implicit interface routines, but I need the %VAL( ) and > %LOC( ) constructs. e.g., here is an example from my code: (snip) For use with Fortran pointers, C_LOC() and C_F_POINTER() are part of the Fortran 2003 standard implemented by many current compilers. That might be a better way to go. -- glen
From: Reinhold Bader on 24 Nov 2009 15:52 Hello, James Tursa schrieb: [...] > > function fpGetPr2Double( mx ) result(fp) > implicit none > real(8), pointer :: fp(:,:) > !-ARG > mwPointer, intent(in) :: mx the above line (among others) does not seem to be a Fortran statement - do you run this through a preprocessor before compiling? > !-COM > real(8), pointer :: Apx2(:,:) > common /MatlabAPI_COMA2/ Apx2 > !-LOC > mwSize, parameter :: stride = 1 > mwPointer :: pr > mwSize, pointer :: dims(:) > !----- > if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. & > & mxGetNumberOfDimensions(mx) == 2 ) then > pr = mxGetPr( mx ) > dims => fpGetDimensions( mx ) > call MatlabAPI_COM_Apx2( %VAL(pr), stride, dims ) For this case, the VALUE attribute might be appropriate. If you specify an explicit interface interface subroutine MatlabAPI_COM_Apx2( %VAL(pr), stride, dims ) mwPointer, value :: pr ! let's hope the preprocessor doesn't mangle this ... mwSize, intent(in) :: stride mwSize :: dims(*) end subroutine end interface in the declaration section of your function then you should be able to dispense with specifying %VAL() on the call. > fp => Apx2 > else > nullify( fp ) > endif > return > end function fpGetPr2Double Regards Reinhold
From: James Tursa on 24 Nov 2009 17:05 On Tue, 24 Nov 2009 13:51:23 -0600, dpb <none(a)non.net> wrote: >James Tursa wrote: >> The non-standard %LOC() and %VAL() constructs are available in the >> Intel Fortran and Compaq Fortran compilers that I have (32-bit, >> WinXP). Are these constructs available in other compilers such as >> gfortran, f95, etc? What about linux, mac, etc.? If not, is there a >> workaround for this functionality? I am writing a package for others >> to use and would like it to run in other environments out of the box >> if possible. Thanks. >> >> James Tursa > >Did you check the comparison pages at the Polyhedron site? IIRC it has >an "extensions supported" category for most compilers... > ><www.polyhedron.com.uk> (otomh, I _think_ that's home page) Good thought. I looked here but they don't list LOC or VAL: http://www.polyhedron.com/pb05-win32-language0html http://www.polyhedron.com/pb05-linux-language0html James Tursa
From: James Tursa on 24 Nov 2009 17:12
On Tue, 24 Nov 2009 21:52:06 +0100, Reinhold Bader <Bader(a)lrz.de> wrote: >> mwPointer, intent(in) :: mx > >the above line (among others) does not seem to be a Fortran statement - do you >run this through a preprocessor before compiling? > Yes. mwPointer and mwSize are token replaced by a pre-processor with integer*4 or integer*8 as appropriate for the installation. James Tursa |