- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'd like to return a 2d array from a fortran subroutine to the calling c++ function.
My current fortran test:
SUBROUTINE ANALYSE (FILE, RESULTS, NUMRESULTS)
!DEC$ ATTRIBUTES C, REFERENCE :: ANALYSE
INTEGER :: NUMRESULTS
INTEGER, pointer :: RESULTS(:,:)
CHARACTER*256 FILE
INTEGER ALLOC_ERR
NUMRESULTS = 3
ALLOCATE (RESULTS(NUMRESULTS,2),STAT = ALLOC_ERR)
RESULTS(1,1) = 0
RESULTS(1,2) = 1
RESULTS(2,1) =2
RESULTS(2,2) =3
RESULTS(3,1) =4
RESULTS(3,2) =5
END
and the c++ counterpart:
extern "C" void analyse (char* FILE, int** RESULTS, int * NUMRESULTS);
void TestClass::Testfunction()
{
int** res= new (int*);
int numres;
analyse(strFilename.ToAscii(), res,numres);
DoSomethingWithTheResults(res,numres);
}
The problem is that the dereferencing of the res pointer in fortran results in heap problems.
What is the right way to do it ?
Thanks in advance,
Stefan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
subroutine ANALYSE (pResults, dim1, dim2) bind(C)
use ISO_C_BINDING
type(C_PTR):: pResults !interoperable with void**
integer(C_INT):: dim1, dim2
integer, allocatable:: MyMat(:,:)
dim1 = 42
dim2 = 26
!Note the reverse order of dimensions between C and Fortran
allocate(MyMat(dim2,dim1))
MyMat(:,:) = 999
pResults = C_LOC(MyMat)
end subroutine ANALYSE
=============================================
extern "C" void ANALYSE(int** p, int& dim1, int& dim2)
...
int** p;
int dim1, dim2;
ANALYSE(p, dim1, dim2);
for (int i=0; i
printf("%4d", *(p + i*dim2 + j));
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
for (j = 2; j <= i__2; ++j) {
int i__3 = j - 1;
for (int i__ = 1; i__ <= i__3; ++i__)
aa[i__ + j * aa_dim1] = aa[j + i__ * aa_dim1] + bb[i__ + j *
bb_dim1];
}
There is no Fortran correspondence to C ** definition (array of pointers), unless, as Jugoslav shows, you declare an explicit C_PTR array.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
subroutine ANALYSE (pResults, dim1, dim2) bind(C)
use ISO_C_BINDING
type(C_PTR):: pResults !interoperable with void**
integer(C_INT):: dim1, dim2
integer, allocatable:: MyMat(:,:)
dim1 = 42
dim2 = 26
!Note the reverse order of dimensions between C and Fortran
allocate(MyMat(dim2,dim1))
MyMat(:,:) = 999
pResults = C_LOC(MyMat)
end subroutine ANALYSE
=============================================
extern "C" void ANALYSE(int** p, int& dim1, int& dim2)
...
int** p;
int dim1, dim2;
ANALYSE(p, dim1, dim2);
for (int i=0; i
printf("%4d", *(p + i*dim2 + j));
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is no correspondence in its general case (array of pointers), but you can interoperate with a function argument of type something** or something*&, which essentially represents a pointer [to a 1-D array] passed by reference, as in my sample above.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
integer, allocatable:: MyMat(:,:)
dim1 = 42
dim2 = 26
!Note the reverse order of dimensions between C and Fortran
allocate(MyMat(dim2,dim1))
MyMat(:,:) = 999
pResults = C_LOC(MyMat)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
subroutine ANALYSE (pResults, dim1, dim2) bind(C)
use ISO_C_BINDING
type(C_PTR):: pResults !interoperable with void**
integer(C_INT):: dim1, dim2
integer, allocatable:: MyMat(:,:)
dim1 = 42
dim2 = 26
!Note the reverse order of dimensions between C and Fortran
allocate(MyMat(dim2,dim1))
MyMat(:,:) = 999
pResults = C_LOC(MyMat)
end subroutine ANALYSE
=============================================
extern "C" void ANALYSE(int** p, int& dim1, int& dim2)
...
int** p;
int dim1, dim2;
ANALYSE(p, dim1, dim2);
for (int i=0; i
printf("%4d", *(p + i*dim2 + j));
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>integer, allocatable:: MyMat(:,:)
Depending on version allocatable gets auto deallocated when descriptor goes out of scope. Consider using pointer
integer, pointer:: MyMat(:,:)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>integer, allocatable:: MyMat(:,:)
Depending on version allocatable gets auto deallocated when descriptor goes out of scope. Consider using pointer
integer, pointer:: MyMat(:,:)
Yes, my bad; at least ALLOCATABLE, SAVE:: for MyMat is required. However, either way (pointer or allocatable), there's no good way to release the memory later (as I wrote the code), because "casting" to a C_PTR (p**) kills all the information needed for successful deallocation.
To overcome the problem, either MyMat should be made persistent (put in a MODULE or COMMON) [which hampers parallelization or code reuse for multi-tasking], or a more complex scheme devised.
To the original poster:
1) If you need the matrix one-off, without the need to deallocate it later, the code above will do, with POINTER or ALLOCATABLE, SAVE added
2) Without ISO_C_BINDING, it is still doable, but you have to rely on Integer (Cray) pointers, which are clumsier and less portable than ISO_C_BINDING. If you use a recent compiler, you'd be better off with the standard solution.

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