From: James on
Hi,

Using c_f_pointer I can use memory allocated in C routines within
fortran. For instance:

program malloc_example
use, intrinsic :: iso_c_binding
implicit none
interface
type(c_ptr) function malloc(ksize) bind(c)
use, intrinsic :: iso_c_binding
implicit none
integer(c_size_t), value :: ksize
end function malloc
subroutine free(p) bind(c)
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value, intent(in) :: p
end subroutine free
end interface
real(c_float), pointer :: tmp(:,:)
type (c_ptr) :: tmp_ptr
integer :: r, c
tmp_ptr = malloc(int(4*2*2,kind=c_size_t))
call c_f_pointer(tmp_ptr, tmp, (/ 2, 2 /))
write (6,*) lbound(tmp)
write (6,*) ubound(tmp)
do r = 1, ubound(tmp, 1)
do c = 1, ubound(tmp, 2)
tmp(r, c) = r * 10 + c
end do
end do
print '(f10.5)', tmp
call free(tmp_ptr)
end program malloc_example

Is there a (standards-compliant) way to set the fortran pointer to
have lower bounds other than 1? I found a discussion from 2 years ago
(http://objectmix.com/fortran/632212-pointer-arithmetic-
c_f_pointer.html) where Steve Lionel says the pointers can be given
alternate bounds, but I can't figure out how to do this...

Many thanks,

--James
From: Richard Maine on
James <james.s.spencer(a)gmail.com> wrote:

> Using c_f_pointer I can use memory allocated in C routines within
> fortran.
....
> Is there a (standards-compliant) way to set the fortran pointer to
> have lower bounds other than 1? ...
> where Steve Lionel says the pointers can be given
> alternate bounds, but I can't figure out how to do this...

You can't directly in c_f_pointer. I think I recall someone once asking
for that as an enhancement to c_f_pointer. On the surface, it seems to
me like a reasonable enhancement, so I checked the f2008 FDIS to see if
it happened to have been done there. Doesn't look like it. Seems to me
like a good example of the kind of question that is bound to pop up
after people get some real experience with f2003 - i.e. the kind of
thing I wanted f2008 to wait for (but I lost that one).

You can use an allocate statement to create pointers with lower bounds
other than 1. The syntax for that is obvious enough that I'd expect
people to be able to guess it (assuming they knew how to use an allocate
statement otherwise), but it won't help with allocaions done in C. You
can also get a pointer with lower bounds other than 1 by argument
association with or pointer assignment to something with lower bounds
other than 1. But again, those don't directly apply to things allocated
in C.

The one other way I can think of off the top of my head can apply to
pointers allocated from C, but you have to do it in 2 steps. First use
c_f_pointer to get a Fortran pointer, which wil have lower bounds of 1.
Then use a pointer assignment statement with a bounds-spec list, as in

new_pointer(0:,0:) => old_pointer

That's assuming you might want lower bounds of 0 to match C conventions.
Substitute other desired bounds and ranks as desired.

Note that this form of pointer assignment syntax is an f2003 feature. An
f95 compiler won't necessarily have it, though most f95 compilers today
have at least some f2003 features, so you might be lucky. C_f_pointer is
also an f2003 feature, so if you are using that, your compiler does have
at least some f2003 features and it seems reasonable to hope for the
pointer assignment form. As such things go, this doesn't seem a
particularly difficult one to implement. (Not that I'm an implementor to
know for sure, but that's my guess).

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: Ron Shepard on
In article <1jmrf0p.mpqer1azvjnkN%nospam(a)see.signature>,
nospam(a)see.signature (Richard Maine) wrote:

> The one other way I can think of off the top of my head can apply to
> pointers allocated from C, but you have to do it in 2 steps. First use
> c_f_pointer to get a Fortran pointer, which wil have lower bounds of 1.
> Then use a pointer assignment statement with a bounds-spec list, as in
>
> new_pointer(0:,0:) => old_pointer
>
> That's assuming you might want lower bounds of 0 to match C conventions.
> Substitute other desired bounds and ranks as desired.
>
> Note that this form of pointer assignment syntax is an f2003 feature. An
> f95 compiler won't necessarily have it, though most f95 compilers today
> have at least some f2003 features, so you might be lucky.

You did not mention the other option, which does work for f95 (and
later).

...
call assign2d( old_pointer 0, 0, new_pointer )
...
subroutine assign2d( old_pointer, lb1, lb2, new_pointer )
integer, intent(in) :: lb1, lb2
real, pointer, intent(inout):: new_pointer(:,:)
real, intent(in), target :: old_pointer(lb1:,lb2:)
new_pointer => old_pointer
return

I did not compile this, and it is just from memory, but I think I
got most of this right. After return, this has the same result as
the above f2003 assignment statement. You need a subroutine like
this for all of your data types and kinds, and for all ranks that
you use.

$.02 -Ron Shepard
From: Richard Maine on
Ron Shepard <ron-shepard(a)NOSPAM.comcast.net> wrote:

> In article <1jmrf0p.mpqer1azvjnkN%nospam(a)see.signature>,
> nospam(a)see.signature (Richard Maine) wrote:

> > Note that this form of pointer assignment syntax is an f2003 feature. An
> > f95 compiler won't necessarily have it, though most f95 compilers today
> > have at least some f2003 features, so you might be lucky.
>
> You did not mention the other option, which does work for f95 (and
> later).
>
> ...
> call assign2d( old_pointer 0, 0, new_pointer )
> ...

Ah. Forgot about that option. Thatks for the reminder. I did think about
(and mention) argument association, but I forgot about that kind of
trick. I get confused about the fine points of when a pointer to a dummy
argument really point sto the actual argument (and thus is guaranteed to
persist after the call), but you are probbaly right.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: Ron Shepard on
In article <1jmrx01.ddfd7zs8fs8uN%nospam(a)see.signature>,
nospam(a)see.signature (Richard Maine) wrote:

> Ron Shepard <ron-shepard(a)NOSPAM.comcast.net> wrote:
>
> > In article <1jmrf0p.mpqer1azvjnkN%nospam(a)see.signature>,
> > nospam(a)see.signature (Richard Maine) wrote:
>
> > > Note that this form of pointer assignment syntax is an f2003 feature. An
> > > f95 compiler won't necessarily have it, though most f95 compilers today
> > > have at least some f2003 features, so you might be lucky.
> >
> > You did not mention the other option, which does work for f95 (and
> > later).
> >
> > ...
> > call assign2d( old_pointer 0, 0, new_pointer )
> > ...
>
> Ah. Forgot about that option. Thatks for the reminder. I did think about
> (and mention) argument association, but I forgot about that kind of
> trick. I get confused about the fine points of when a pointer to a dummy
> argument really point sto the actual argument (and thus is guaranteed to
> persist after the call), but you are probbaly right.

Yes, that is the part I was unsure of also. That is, should the
old_pointer(lb1:,lb2:) dummy declaration have a pointer or a target
attribute? I think it is a target, but I'm not 100% sure. It is
not possible to simply compile an example because it is most likely
to work in either case, but the standard only requires it to work
with certain combinations of attributes and intents. The thing that
needs to be avoided is the possibility of copy-in/copy-out for the
old_pointer(:,:) array. For a particular compiler, you can verify
that copy-in/copy-out has not occurred by using either the
nonstandard loc() function or the newer c_loc version, the latter of
which might make sense since c interoperability is already being
used for other aspects of the program.

You can also use this trick to assign a 2D pointer to a 1D array.
It almost always works "correctly" (and it can be verified with the
loc() test), but I'm pretty sure that this version is nonstandard.
However, if I remember correctly f2008 does extend pointer
assignment to these cases in a standard conforming way.

$.02 -Ron Shepard