From: James Tursa on
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
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
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
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
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