john.chludzinski wrote:
> If want a subroutine to have a dummy argument that is a "void" pointer and within the subroutine cast it as a pointer to something specific, how is this best accomplished?
Well, the closed equivalent is Fortran TS 29113:2012, where one can do
the following (note the "TYPE(*)"). As the "2012" implies, that's a
brand new feature, which implies that no compiler has a complete support
for it.
! ----------------------------
implicit none
integer :: i
real :: r
i = 55
r = -42.0
call bar(i,1)
call bar(r,2)
contains
subroutine bar(x, j)
use iso_c_binding
type(*), target, intent(in) :: x
integer, value :: j
integer, pointer :: val_i
integer, pointer :: val_r
if (j == 1) then
call c_f_pointer (c_loc (x), val_i)
print *, 'Value i = ', i
elseif (j == 2) then
call c_f_pointer (c_loc (x), val_i)
print *, 'Value r = ', r
end if
end subroutine bar
end
! ----------------------------
$ gfortran foo.f90 && ./a.out
Value i = 55
Value r = -42.0000000
* * *
That feature requires gfortran 4.8 and there are still some issues with
assumed-rank arrays.
Another related feature is CLASS(*) of Fortran 2003. Even though the
year 2003 is a while back, it took (and takes) a while until compiler
have implemented that feature. gfortran presumably will get this feature
soon, but it hasn't yet. (Though, draft patches exist.)
The equivalent program like follows; it rather matches C++'s run-time
type system (RTTS) than C's (and C++'s) "void *":
! ----------------------------
implicit none
integer :: i
real :: r
i = 55
r = -42.0
call bar(i)
call bar(r)
contains
subroutine bar(x)
class(*) :: x
select type(x)
type is (integer)
print *, 'Value i = ', x
type is (real)
print *, 'Value r = ', x
end select
end subroutine bar
end
! ----------------------------
ftn -h cpu=x86-64 class_u_1.f90 && ./a.out
Value i = 55
Value r = -42.
* * *
Other possibilities are to handle the conversion in the caller not in
the callee. For instance, to convert everything to a "TYPE(C_PTR)", pass
it as C pointer, and convert it back via C_F_POINTER in the called
procedure. That's a Fortran 2003 possibility which is widely supported.
* * *
The fourth possibility is to use TRANSFER, which works since Fortran 90.
See Glen's email for an example.
It really depends on what you want to do with the passed data, i.e.
whether you just want to treat is as junk of (contiguous or
noncontiguous) bytes or whether you want to convert it back to something
else or �
In my opinion, if you just want to treat is a bytes ("void *buffer")
then TYPE(*) - possibly together with dimension(..) - is the best option
(and hence also used by the MPI 3 specification). Or for wider compiler
compatibility, TYPE(C_PTR) instead. If you want to convert it back,
CLASS(*) might be the best option. And for widest compiler
compatibility, TRANSFER is best as it already exists since Fortran 90.
But again, even my suggestion might be different, depending on the exact
use.
Tobias