- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should have used "-std=f2008ts".
Harald
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Harald wrote:
You should have used "-std=f2008ts".
Harald
Good point, thanks for bringing this to my attention.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
How would you write such a procedure in Fortran?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
Further down in the appendix:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page