Fortran/C interfacing

Tobias Burnus burnus@net-b.de
Fri Nov 14 21:01:00 GMT 2014


Am 14.11.2014 um 16:56 schrieb Thomas Schwinge:
> Hi!
>
> On Wed, 12 Nov 2014 11:06:26 +0100, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Tue, Nov 11, 2014 at 01:53:23PM +0000, Julian Brown wrote:
>>> [OpenACC libgomp changes][openacc.f90, and exporting symbols in libgomp.map]
>>>
>>>
>> Somebody recently suggested (for OpenMP) that we just should use
>> bind(C) in the Fortran module, it is too late for OpenMP, as we
>> have to keep the *_ entrypoints for compatibility anyway, but
>> for OpenACC and new OpenMP functions supposedly you could avoid
>> exporting all the *_ wrappers and use * directly.
> Tobis, as our local expert :-) -- how does that "resonate" with the
> discussion (and implementation) about Fortran/C interfacing

Unfortunately, it a wrapper either on C or on Fortran side is unavoidable.

For C/C++, one has has:
   void* acc_copyin(h_void*, size_t );

That matches (if one ignores the return type):
   subroutine acc_copyin(a, len) bind(C)
     use iso_c_binding, only: c_size_t
     type(*) :: a
     integer(c_size_t) :: len

If one looks at Fortran's first interface, it seems to match:
   subroutine acc_copyin(a, len )
     type:: a
     integer :: len

However, a default-size integer in Fortran is usually* 4-bytes wide 
while size_t on most 64bit systems** is 8-bytes wide. As Fortran doesn't 
automatically convert the integer type, I think there is no way but 
providing additionally a function which takes an "int"/default-kind 
integer. (* unless one uses -fdefault-integer-8; ** such as x32.)

I think in the current version of the patch – I haven't re-checked –, 
one provides both a function for int32 and int64, one matching a 32 and 
one a 64 bit integer. Additionally, it permits to use >2GB arrays. In 
principle, one of the versions could directly invoke the C function 
without the wrapper [where c_size_t == kind(integer)] - but that would 
require come conditional compilation.
Whether one has a trailing "_" and whether one implements it in C or in 
Fortran doesn't really matter.

The second Fortran interface is:

   subroutine acc_copyin(a)
     type, dimension(: [,:]…) :: a

which can be best writtin in modern Fortran as:
    class(*), dimension(..) :: a
and which, knowing the internal implementation, I wrote as
    type(*), dimension(..) :: a
as it avoids some extra code on the caller side - but it is not fully 
standard conform. On the other hand, "type(*), dimension(..)" can be 
also marked as BIND(C).

There is no C equivalent but one can use something like
    call acc_copyin(c_loc(a), size(a)*storage_size(a)/8)
to convert it to the C form of the function.

Again, this conversion can be done either in Fortran or in C. One just 
needs to take the first field of the array descriptor - the address of 
the actual data - and needs to extract the size of an element and the 
number of elements. (Caveat: The current code only works if the array is 
contiguous and the argument is not an assumed-size array.)


Thus, all in all, I think the current implementation is okay. However, 
if someone has a better suggestion, I am interested.

Tobias

PS: I am happy that TYPE(*) and DIMENSION(..) exist (both in the 
standard and in the compiler) as they make life much simpler. Otherwise, 
providing an explicit interface would be tediuous for intrinsic types 
and impossible for derived types.



More information about the Gcc-patches mailing list