Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29348 Discussions

What hath "TS 29113/TS 18508" wrought!?

FortranFan
Honored Contributor III
3,399 Views

The following simple code compiles fine with the latest Intel Fortran compiler 2015, update 2 but it gives an error with gfortran, a GCC 5.0 development trunk version.

The error, as shown below, has to do with "TS 29113/TS 18508", presumably related to further interoperability features with C in the next standard.   Now I am not sure if Intel has started implementing any of these features yet, so Intel Fortran compiler behavior may not be relevant yet.

However, looking at TS 29113, I don't see anything that states this code is in error; the code is so basic, if this is not allowed, then I wonder what is!  My take on this is gfortran has a bug; I would appreciate any comments and feedback on this.

module m

   use, intrinsic :: iso_c_binding, only : c_funptr, c_f_procpointer

   implicit none

   private

   abstract interface

      subroutine ifoo()
      end subroutine ifoo

   end interface

   type(c_funptr)           :: c_f_ptr
   procedure(ifoo), pointer :: f_f_ptr

contains

   subroutine set_fptr()

      call c_f_procpointer(c_f_ptr, f_f_ptr)

   end subroutine set_fptr

end module m

 

Compilation error with options -Wall -std=f2008 in gfortran :

m.f90:23.36:
      call c_f_procpointer(c_f_ptr, f_f_ptr)
                                    1
Error: TS 29113/TS 18508: Noninteroperable procedure pointer at (1) to C_F_PROCPOINTER

 

0 Kudos
20 Replies
TimP
Honored Contributor III
3,369 Views

I don't see any such complaint from gfortran 5.0.0 20150326 (trunk as of 2 days ago).  The only complaint I see is about the tabs which appear when I copy and paste source from your post.

I ran the full test suite but apparently I no longer have privilege to post the results on the gcc site.  There are an inordinate number of failures associated with newer gfortran features on Windows, but it doesn't seem to impact usability.  ifort probably doesn't fare well either when running the gfortran test suite, but it's hard to do on account of the inconsistent options.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,369 Views

FortranFan,

caviat: I haven't attempted your source above, nor use those interop features like you do in your source...

Reading the 15.0 referenc guide

C_F_PROCPOINTER

Intrinsic Module Subroutine: Associates a Fortran pointer of type INTEGER with the target of a C function pointer.

Module

USE, INTRINSIC :: ISO_C_BINDING

Syntax

CALL C_F_POINTER(cptr, fptr)

cptr
 
(Input) Is a scalar of derived type C_FUNPTR. Its value is the C address of a procedure that is interoperable.

fptr
 
(Output) Is a Fortran pointer of type INTEGER. It becomes pointer-associated with the target of cptr.

The above text leads me to believe the pointer must be to than of an INTEGER FUNCTION.

You are using it as a SUBROUTINE.

What happens if you change "subrouting ifoo()" to "integer function ifoo()"?

Jim Dempsey

0 Kudos
Harald
Beginner
3,369 Views

You should have used "-std=f2008ts".

Harald

 

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

Jim,

Thanks for your comments, but I think that brings up another issue which is an inadequacy in some aspects of Intel Fortran compiler documentation.

The latest standard documentation shows the following:

c_f.png

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

I think I know what I did wrong: forgot to add BIND(C) attribute on the interface definition.  The code shown below compiles ok with gfortran.  But if that's the case, then I wonder if it really has anything to do with "TS 29113/TS 18508" and if the gfortran error shown the original post is misleading; but that's for GCC folks to think about.

And this brings up the question: should Intel Fortran raise an error/warning when BIND(C) is missing on the interface definition especially if -standard-semantics or -stand:f08 (or f03) is in effect?

Thanks,

module m

   use, intrinsic :: iso_c_binding, only : c_funptr, c_f_procpointer

   implicit none

   private

   abstract interface

      subroutine ifoo() bind(c)  !.. BIND(C) added
      end subroutine ifoo

   end interface

   type(c_funptr)           :: c_f_ptr
   procedure(ifoo), pointer :: f_f_ptr

contains

   subroutine set_fptr()

      call c_f_procpointer(c_f_ptr, f_f_ptr)

   end subroutine set_fptr

end module m

 

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

Tim Prince wrote:

I don't see any such complaint from gfortran 5.0.0 20150326 (trunk as of 2 days ago).  ..

Tim,

See Quote #4, perhaps you have "-stdf2008ts".  Otherwise, it's possible this aspect of C interoperability is in a flux in gfortran and compiler response may change from build to build due to code updates.

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

Harald wrote:

You should have used "-std=f2008ts".

Harald

Good point, thanks for bringing this to my attention.

0 Kudos
Steven_L_Intel1
Employee
3,369 Views

Intel Fortran never enforced the restrictions that arguments to routines in ISO_C_BINDING be interoperable. That requirement was lifted in TS29113, so Intel Fortran was "ahead of the curve" on that. Note that the restrictions were not in the form of constraints, so checking was not required. In F2008, the interoperable requirement (on the programmer) is still there.

The text in our documentation for C_F_PROCPOINTER referring to "type INTEGER" is an error. I will get that fixed. The fptr must be a procedure pointer.

0 Kudos
JVanB
Valued Contributor II
3,369 Views

Just for the sake of being totally OT, why didn't varargs procedures in interface bodies make it into the upgraded C interoperability? In MacOS, everything seems to go through a varargs function which is awkward to invoke currently. Seems like it would be more difficult for a Fortran compiler to document this than implement it.

 

0 Kudos
Steven_L_Intel1
Employee
3,369 Views

The "interop TS" was almost entirely driven by MPI3. I don't recall any discussion of varargs and am uncertain how you would map that into a Fortran concept.

0 Kudos
JVanB
Valued Contributor II
3,369 Views

If you are uncertain, then how does !DIR$ ATTRIBUTES VARYING work? Just plop that into the interface body for a procedure with the BIND attribute in some way acceptable to the standardization committee and it would be very helpful.

 

0 Kudos
IanH
Honored Contributor III
3,369 Views

How would you write such a procedure in Fortran?

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

Repeat Offender wrote:

Just for the sake of being totally OT, why didn't varargs procedures in interface bodies make it into the upgraded C interoperability? In MacOS, everything seems to go through a varargs function which is awkward to invoke currently. Seems like it would be more difficult for a Fortran compiler to document this than implement it.

How does the following from TS 29113 help in this situation?

c_f_2.png

Further down in the appendix:

c_f_3.png

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,369 Views

FortranFan,

Can you append the C "fat binding" side to your example?

The general problem with "fat binding" is that the internal structure of the array descriptors is implementation dependent. For "portable" code, you will need (when using array descriptor or pointer to array slice) is for the Fortran caller to pass in to the C routine the reference (address) of the Fortran array descriptor/pointer. The C routine, will receive the Fortran array descriptor as an opaque object (note, for C++ the opaque object can have member functions, such as ()[]). The C routine can perform a callback function to the vendor's Fortran runtime library, or to a user Fortran subroutine, to obtain the pointer to the data and the ranks, sizes, stride, etc. IOW the vendor or user supplied routine will accept a vendor preferred array descriptor and return a (TBD) universal C friendly array descriptor/accessor.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

jimdempseyatthecove wrote:

FortranFan,

Can you append the C "fat binding" side to your example?

..

Jim,

Here's the link to TS 29113 if you're interested.

Shown below are the some additional details of the example and "fat binding" and use of optional arguments:

c_f_4.png

In response to RO's question, I was simply wondering if it is possible to make use of any of the TS 29113 enhancements in a way that can work with variable argument C procedures. 

 

0 Kudos
Steven_L_Intel1
Employee
3,369 Views

Repeat Offender wrote:

If you are uncertain, then how does !DIR$ ATTRIBUTES VARYING work? 

This doesn't match C varying arguments, which use a list-type structure. It also doesn't work well with the notion of an unlimited number of arguments since Fortran really doesn't have that concept (except with certain intrinsics such as MAX and MIN, which are not readily specifiable in an explicit interface.)

I suppose what could be done is add a VARYING attribute that must be on the last argument, specifying that there can be one or more of that type. I'm not sure how to work in argument name keywords, though.

0 Kudos
JVanB
Valued Contributor II
3,369 Views

We seem to be on completely different planets, so I offer an example with !DIR$ ATTRIBUTES VARYING to make more clear my ideas.

module M
   use ISO_C_BINDING
   implicit none
   interface
      function wsprintf(lpOut,lpFmt)
         import
         implicit none
!DEC$ ATTRIBUTES C, alias: 'wsprintfA' :: wsprintf
!DIR$ ATTRIBUTES varying :: wsprintf
         integer(C_INT) wsprintf
         character(kind=C_CHAR), intent(out) :: lpOut(*)
         character(kind=C_CHAR), intent(in) :: lpFmt(*)
      end function wsprintf
   end interface
end module M

program P
   use M
   implicit none
   character(len=80,kind=C_CHAR) lpOut
   character(len=80,kind=C_CHAR) lpFmt
   character(len=80,kind=C_CHAR) mess
   integer(C_INT) variable
   integer(C_INT) R

   lpFmt = '%s = %d'//achar(10)//achar(0)
   mess = 'The variable'//achar(0)
   variable = 42
   R = wsprintf(lpOut,lpFmt,C_LOC(mess),variable)
   write(*,'(a)') lpOut(1:index(lpOut,achar(0))-1)
end program P

Output with ifort (64-bit Windows):

The variable = 42

Keywords aren't going to work and I'm not asking for callbacks. Why doesn't the above match C varying arguments?

0 Kudos
FortranFan
Honored Contributor III
3,369 Views

Repeat Offender wrote:

We seem to be on completely different planets, ..

If one looks at this and this as well as the example from the appendix in TS 29113, it appears the general thinking is to employ C wrappers to get around situations that relate to any gaps in standard aspects of Fortran/C interoperability.  Is that too onerous for Mac OS APIs?

0 Kudos
JVanB
Valued Contributor II
3,369 Views

Employing C wrappers was the f77 way. Since ifort already has the solution to the problem it seems surprising that there isn't a similar solution in the standard.

 

0 Kudos
IanH
Honored Contributor III
3,259 Views

The facilities in the current standard are symmetric - an interoperable procedure can be written in either Fortran or C.  Variadic functions are not symmetric in this manner, with the Fortran language as it is now.  It might be only a philosophical barrier, but I think that a sufficient reason for the absence of interoperability with variadic functions.  You would at least want to have a concept of how they could be done in Fortran worked out, before you specified the Fortran to C interoperable case, just so you didn't make things more difficult for later language evolution.

We are a lot better off today than we were with Fortran 77.

0 Kudos
Reply