- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi again.
Consdier the following Fortran routine:
integer function demo( k ) bind(C)
use, intrinsic :: ISO_C_BINDING, only: C_INT
implicit none
integer(C_INT), intent(in), value :: kinteger :: i
i = k ! fatal runtime if value attribute is removed above
demo = 0
return
end function demo
If I invoke that routine from C using either
int foo = demo(100)
or
int argument = 100
int foo = demo(argument)
everything runs as expected. But why should I need the VALUE attribute on the dummy variable k? Surely the ISO_C_BINDING is supposed to take care of the calling conventions! If I remove the VALUE attribute, the code still compiles and links. But I get a fatal runtime error (undefined address) on the i = k assignment. Notice that I am not trying to make an assignment *to* the dummy argument. I'm just trying to *use* the value which I expect to have passed via the dummy argument. This has all the hallmarks of trying to use reference semantics on a value object. But again, should not the ISO_C_BINDING take care of this? I'm pretty sure I've seen examples of floating-point code which work wthout the VALUE attribute.
So far I have tried this only for C_INT. I figure I should not even try C_FLOAT or C_CHAR until I understand how C_INT works. I have also been reading ISO/IEC FCD 1539-1:2004(E) but have not found an explanation for the behavior I see. If anyone can explan this, I'd appreciate it. Useful pointers into the standard are also welcome.
I am using IVF 11.1.054
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First of all, ISO_C_BINDING has nothing to do with this. It's just a module with declarations. What you're really asking is if BIND(C) changes the argument passing convention to be "by value". The answer to that is "No". The standard sez....
4 A Fortran procedure interface is interoperable with a C function prototype if
5 (1) the interface has the BIND attribute;
6 (2) either
7 (a) the interface describes a function whose result variable is a scalar that is interoperable
8 with the result of the prototype or
9 (b) the interface describes a subroutine, and the prototype has a result type of void;
10 (3) the number of dummy arguments of the interface is equal to the number of formal parameters
11 of the prototype;
12 (4) any dummy argument with the VALUE attribute is interoperable with the corresponding
13 formal parameter of the prototype;
14 (5) any dummy argument without the VALUE attribute corresponds to a formal parameter
15 of the prototype that is of a pointer type, and the dummy argument is interoperable with
16 an entity of the referenced type (C International Standard, 6.2.5, 7.17, and 7.18.1) of the
17 formal parameter; and
18 (6) the prototype does not have variable arguments as denoted by the ellipsis (...).
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I forgot to mention that in my C++ code I have declared demo() external as follows:
extern "C" int demo(int kappa);
And my OP is just a stripped down example. I am actually able to pass (integer) values back and forth both on the stack and on the heap to do useful work, provided that the stack values are declared with the VALUE attribute.
I'm hoping I've done something trivially foolish. Otherwise, I can share an example project with premier support.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Changing the definition of the function to
integer(C_INT) function demo( k ) bind(C)
did not help but is probably a good idea.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First of all, ISO_C_BINDING has nothing to do with this. It's just a module with declarations. What you're really asking is if BIND(C) changes the argument passing convention to be "by value". The answer to that is "No". The standard sez....
4 A Fortran procedure interface is interoperable with a C function prototype if
5 (1) the interface has the BIND attribute;
6 (2) either
7 (a) the interface describes a function whose result variable is a scalar that is interoperable
8 with the result of the prototype or
9 (b) the interface describes a subroutine, and the prototype has a result type of void;
10 (3) the number of dummy arguments of the interface is equal to the number of formal parameters
11 of the prototype;
12 (4) any dummy argument with the VALUE attribute is interoperable with the corresponding
13 formal parameter of the prototype;
14 (5) any dummy argument without the VALUE attribute corresponds to a formal parameter
15 of the prototype that is of a pointer type, and the dummy argument is interoperable with
16 an entity of the referenced type (C International Standard, 6.2.5, 7.17, and 7.18.1) of the
17 formal parameter; and
18 (6) the prototype does not have variable arguments as denoted by the ellipsis (...).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you, Steve. What you've been telling me finally dropped into place.
What I take from this is
(1) The ISO_C_BINDING module is just declarations/definitions.
(2) The ISO_C_BINDING module is just declarations/definitions. Really!
(3) The interoperability of Fortran 2003 does little more than require implementors to observe the order of formal arguments/parameters, the return value and the long-ago established value/reference semantics for each of these.
I was blinded by a preconceived and misplaced hope that Fortran 2003 was going to free me from ever having to think about calling conventions again. I was so wrong. So blinded, I managed to miss the very direct language in the standard. Thank you for setting me straight. Clear now. I'm even passing character data back and forth now and appreciate the C_NULL_CHAR very much.
Thanks for patiently explaining this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, actually, Fortran 2003 does free you. When you are coding in C you need to keep straight whether an argument is expected as int or *int. Same in Fortran.
The C interoperability features free you from vendor extensions to specify things such as pass-by-value, knowing how derived types are padded, knowing how various types are returned as function results, and having a portable way of declaring Fortran variables that match up with corresponding variables in C. Oh, naming conventions are also eased.
What confuses a lot of people, including at one point some of our own developers, is that BIND(C) is not the same as our !DEC$ ATTRIBUTES C.
The C interop features are very powerful and, for the first time, allow writing portable, standard-conforming code that calls and can be called by C. This is nothing to sneeze at. There's really a lot going on behind the scenes, especially in cases where Fortran compilers create their own conventions. (For example, how is a COMPLEX function value returned? Fortran and C do it differently by default.) No hidden arguments allowed when using BIND(C)!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see your point. As an occasional Fortran user over several generations of the DEC compiler I was just as happy with !DEC$ since it was (is) consistent over time. Yes, learning it the first time was confusing. But I got pretty good at using it. I do see that the new way ensures portability, which !DEC$ does not. And I for one say "good riddance!" to hidden length arguments!
Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page