- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello!
I faced a problem when trying to create mixed language program - C main program and FORTRAN library. In FORTRAN I made a COMMON block with two allocatable arrays, and I want to have access to both of them from C code. Everything is fine during building and with access to the first one, but while running program can't obtain correct address of the second array (its address is 0x00000004) and breaks with error. Text of both codes is below.
Any suggestion will be highly appreciated - is it possible to correct the code somehow, or I need to create additional subroutine to access data in COMMON block. Of course, I can make several COMMONs for each array, but it also is not convenient.
Thanks for your answer and help.
FORTRAN code*****************************************************
C------------------------------------------------
SUBROUTINE ALLOC_ARRAYS
COMMON /MYARRS/ IAR1,IAR2
INTEGER, DIMENSION(:), POINTER :: IAR1
INTEGER, DIMENSION(:), POINTER :: IAR2
INTEGER I
C--------
ALLOCATE(IAR1(100),IAR2(100))
DO I = 1,100
IAR1(I) = I*12
IAR2(I) = I*10
END DO
C--------
END
C------------------------------------------------
SUBROUTINE DEALLOC_ARRAYS
COMMON /MYARRS/ IAR1,IAR2
INTEGER, DIMENSION(:), POINTER :: IAR1
INTEGER, DIMENSION(:), POINTER :: IAR2
C--------
DEALLOCATE(IAR1,IAR2)
C--------
END
C------------------------------------------------
C code*****************************************************
struct for_arrays
{
int *piAR1;
int *piAR2;
};
extern "C"
{
void ALLOC_ARRAYS();
void DEALLOC_ARRAYS();
struct for_arrays MYARRS;
}
void main()
{
ALLOC_ARRAYS();
// O.k. here
int it1 = MYARRS.piAR1[5];
// Error here
int it2 = MYARRS.piAR2[6];
DEALLOC_ARRAYS();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can't share pointers to deferred-shape arrays in COMMON. I think the following modification would work, though.
MODULE ARRAYS_MOD USE, INTRINSIC :: ISO_C_BINDING TYPE(C_PTR) :: P_IAR1, P_IAR2 COMMON /MYARRS/ P_IAR1, P_IAR2 BIND(C) :: /MYARRS/ INTEGER, DIMENSION(:), POINTER :: IAR1 INTEGER, DIMENSION(:), POINTER :: IAR2 END MODULE ARRAYS_MOD C------------------------------------------------ SUBROUTINE ALLOC_ARRAYS USE ARRAYS_MOD INTEGER I C-------- ALLOCATE(IAR1(100),IAR2(100)) P_IAR1 = C_LOC(IAR1) P_IAR2 = C_LOC(IAR2) DO I = 1,100 IAR1(I) = I*12 IAR2(I) = I*10 END DO C-------- END C------------------------------------------------ SUBROUTINE DEALLOC_ARRAYS USE ARRAYS_MOD C-------- DEALLOCATE(IAR1,IAR2) C-------- END
Do keep in mind that Fortran arrays are 1-origin and C arrays are 0-origin.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can't share pointers to deferred-shape arrays in COMMON. I think the following modification would work, though.
MODULE ARRAYS_MOD USE, INTRINSIC :: ISO_C_BINDING TYPE(C_PTR) :: P_IAR1, P_IAR2 COMMON /MYARRS/ P_IAR1, P_IAR2 BIND(C) :: /MYARRS/ INTEGER, DIMENSION(:), POINTER :: IAR1 INTEGER, DIMENSION(:), POINTER :: IAR2 END MODULE ARRAYS_MOD C------------------------------------------------ SUBROUTINE ALLOC_ARRAYS USE ARRAYS_MOD INTEGER I C-------- ALLOCATE(IAR1(100),IAR2(100)) P_IAR1 = C_LOC(IAR1) P_IAR2 = C_LOC(IAR2) DO I = 1,100 IAR1(I) = I*12 IAR2(I) = I*10 END DO C-------- END C------------------------------------------------ SUBROUTINE DEALLOC_ARRAYS USE ARRAYS_MOD C-------- DEALLOCATE(IAR1,IAR2) C-------- END
Do keep in mind that Fortran arrays are 1-origin and C arrays are 0-origin.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks you much, it works!
Just one more question – this code at my system works if I only comment the string
BIND(C) :: /MYARRS/
Without this change both pointers in C code are equal to zero. Do you have any idea why?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you still have the same C code - the default binding label in Fortran with BIND(C) is a lower case variant of the Fortran name. Either rename the structure object in C to the lower case variant (i.e. `struct for_arrays MYARRS;` goes to `struct for_arrays myarrs;` ) or add the NAME specifier to the BIND statement to get explicit about the C name for the common block (`BIND(C, NAME='MYARRS') :: /MYARRS/`).
(I can never remember whether the Fortran default for BIND(C) is upper or lower case, so I am always explicit about the binding label.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Everything works fine, thank you again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, Ian, I forgot about the downcasing.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page