- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As I understand it pass-by-reference is not supported from C++ to Fortran is not supported, or at least not part of the language. Nevertheless it seems to enable passing a value to a Fortran routine whose argument is not declared to have the 'value' attribute. The code below illustrates this:
#ifdef FORTRAN subroutine mysub1(i) bind(c,name='mysub1') use iso_c_binding, only: c_int integer(c_int), intent(in), value :: i write(*,'(a,i0)') 'mysub1: i = ',i end subroutine mysub1 subroutine mysub2(i) bind(c,name='mysub2') use iso_c_binding, only: c_int integer(c_int), intent(in) :: i write(*,'(a,i0)') 'mysub2: i = ',i end subroutine mysub2 subroutine mysub3(i) bind(c,name='mysub3') use iso_c_binding, only: c_int integer(c_int), intent(in), value :: i write(*,'(a,i0)') 'mysub3: i = ',i end subroutine mysub3 #else extern "C" { void mysub1(int&); void mysub2(int&); void mysub3(int); }; int main (int, char**) { int i=3; mysub1(i); mysub2(i); mysub3(i); return 0; } #endif
To use it save to a file e.g. example.txt then on a command line do the following:
ifort /c /fpp /DFORTRAN /Tf example.txt /free /Foexample_f.obj
cl /Tpexample.txt /Feexample.exe example_f.obj
Then run it: example.exe
mysub1: i = 2357888
mysub2: i = 3
mysub3: i = 3
The way mysub2 is declared seems to give the required behaviour but I don't think it's standards conforming. So my questions are:
1) what are the problems with doing this?
2) can the current behaviour be relied upon?
3) is it advisable to convert to the declaration used in mysub3?
Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In your usage with mysub1, your result will vary between 32 and 64 bit modes, assuming 32 bit default integer. you have c_intptr_t. As far as I know, Fortran standard doesn't specify anything about c++ reference, but if your c++ follows the usual rules about interoperability between c++ reference and c pointer, you will be ok.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your understanding is not correct - pass-by-reference absolutely is supported and is what you get if you omit the VALUE attribute from an argument to a procedure with BIND(C).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did have a look at one stage through the C++ standard, and, from what I can remember, I don't think there are rules for interoperability between C pointers and C++ references, and there are explicit differences (references may not require storage and you can't have a pointer to a reference). I think it is a pretty safe assumption that C++ references are implemented using C pointers when they appear in the formal parameter list of the function - it is possible that practical considerations even require that implementation. However, I personally do not rely on this assumption.
To highlight, this (mysub4) is the example that is missing from the code in #1, that shows conforming "pass by reference" (informal sense - neither Fortran nor C++ formally describe things that way).
#ifdef FORTRAN subroutine mysub1(i) bind(c,name='mysub1') use iso_c_binding, only: c_int integer(c_int), intent(in), value :: i write(*,'(a,i0)') 'mysub1: i = ',i end subroutine mysub1 subroutine mysub2(i) bind(c,name='mysub2') use iso_c_binding, only: c_int integer(c_int), intent(in) :: i write(*,'(a,i0)') 'mysub2: i = ',i end subroutine mysub2 subroutine mysub3(i) bind(c,name='mysub3') use iso_c_binding, only: c_int integer(c_int), intent(in), value :: i write(*,'(a,i0)') 'mysub3: i = ',i end subroutine mysub3 subroutine mysub4(i) bind(c,name='mysub4') use iso_c_binding, only: c_int integer(c_int), intent(in) :: i write(*,'(a,i0)') 'mysub4: i = ',i end subroutine mysub4 #else extern "C" { void mysub1(int&); void mysub2(int&); void mysub3(int); void mysub4(int*); } int main (int, char**) { int i=3; mysub1(i); mysub2(i); mysub3(i); mysub4(&i); // Pass address of i. return 0; } #endif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First of all, Fortran supports interoperability with C, not C++. To the extent that you can make C++ look like C, it works.
Fortran supports interoperability of argument passing two ways. Assuming an interoperable (BIND(C)) interface, Assuming that you're not declaring a dummy argument of a Fortran kind that triggers passing by "C descriptor" (TS29113 or Fortran 2015), the standard says:
- any scalar dummy argument with the VALUE attribute is interoperable with the corresponding formal parameter of the prototype,
- any dummy argument without the VALUE attribute corresponds to a formal parameter of the prototype that is of a pointer type,
It doesn't talk about "pass by reference", but realistically that's what it means by "a formal parameter of the prototype that is of a pointer type".
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page