- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi There,
I have an ifort 9.1 and a g++ 4.3.2 running on my OpenSuSE 11.1 box. I pass a few variables between Fortran and C++ where the unusual thing is that the Fortran code is the still maintained and the C++ code is the legacy. It means that Fortran calls C++ and not backwards.
All goes well for simple variables and even for arrays until I try to pass a dynamic array (defined as allocatable and allocated runtime). The values I get there are really weird, have nothing to do what was there before. On the other hand I am a C++ guy (doing fortran for three days) so I might miss something obvious.
What works fine:
What does not work (passes weird values):
So when I do the following calls:
Then the first call passes the proper values to C++ and the second call passes seemingly a bit of junk. I tried with integers instead of reals to see if something is just mixed up with reals but that does not look like the case - values are messy for integer arrays too.
The C(++) call is defined as:
So... that is the problem. Static allocation looks to pass proper values, dynamic passes wrong ones even if those look to be the same when printed from the Fortran code to the screen.
Cheers,
Sandor
I have an ifort 9.1 and a g++ 4.3.2 running on my OpenSuSE 11.1 box. I pass a few variables between Fortran and C++ where the unusual thing is that the Fortran code is the still maintained and the C++ code is the legacy. It means that Fortran calls C++ and not backwards.
All goes well for simple variables and even for arrays until I try to pass a dynamic array (defined as allocatable and allocated runtime). The values I get there are really weird, have nothing to do what was there before. On the other hand I am a C++ guy (doing fortran for three days) so I might miss something obvious.
What works fine:
type type1
real*4, dimension(5:10) :: val1
real*4, dimension(10:20) :: val2
end type
type(type1) test1
What does not work (passes weird values):
type type2
real*4, allocatable, dimension(:,:) :: val1
real*4, dimension(:,:) :: val2
end type
type(type2) test2
! ...
allocate(test2%val1(5,10)) ! stat check is not done
allocate(test2%val2(10,20)) ! stat check is not done
So when I do the following calls:
call callcpp(test1)
call callcpp(test2)
Then the first call passes the proper values to C++ and the second call passes seemingly a bit of junk. I tried with integers instead of reals to see if something is just mixed up with reals but that does not look like the case - values are messy for integer arrays too.
The C(++) call is defined as:
extern "C" {
void callcpp_(char *pStruct);
}
void callcpp_(char *pStruct) {
int Pointer1 = 0, Pointer2 = 0;
for (int j = 0; j < 100; j++) { // 100 is just for test
printf("%d TestIntStruct[%d] == %d\n", Pointer1, j, *((int*)(pStruct + Pointer1)));
printf("%d TestIntStruct[%d] == %#12.6g\n", Pointer2, j, *((int*)(pStruct + Pointer2)));
Pointer1 += sizeof(int);
Pointer2 += sizeof(float);
}
}
So... that is the problem. Static allocation looks to pass proper values, dynamic passes wrong ones even if those look to be the same when printed from the Fortran code to the screen.
Cheers,
Sandor
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As you chose not to use a compiler which supports "type, bind(c) :: type2" it seems like bets are off.
I don't see that you followed the textbook suggestions about how an allocatable array might be used in C, which include passing the array by argument association and depending on the compiler to employ copy-in copy-out.
I don't see that you followed the textbook suggestions about how an allocatable array might be used in C, which include passing the array by argument association and depending on the compiler to employ copy-in copy-out.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran allocatable arrays are not the same as C pointers. When you have a derived type component as an allocalatble (or pointer) array, what is actually in the structure is a "descriptor" with much more than just a pointer. The layout of this is described in the Fortran documentation.
If you were using Fortrtan 10.0 or later, you could use the Fortran 2003 interoperability features to make the components of type C_PTR and then use Fortran POINTER arrays, allocating the array and then using C_LOC to convert the Fortran pointer to a C pointer.
Otherwise, you can make the structure element an INTEGER(INT_PTR_KIND()), create POINTER arrays (not ALLOCATABLE) in the function, allocate them and use LOC to get the address.
If you were using Fortrtan 10.0 or later, you could use the Fortran 2003 interoperability features to make the components of type C_PTR and then use Fortran POINTER arrays, allocating the array and then using C_LOC to convert the Fortran pointer to a C pointer.
Otherwise, you can make the structure element an INTEGER(INT_PTR_KIND()), create POINTER arrays (not ALLOCATABLE) in the function, allocate them and use LOC to get the address.

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