Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
10 Views

Access to data in COMMON block from C code

Jump to solution

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();
}

 

0 Kudos

Accepted Solutions
Highlighted
10 Views

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.

Retired 12/31/2016

View solution in original post

0 Kudos
5 Replies
Highlighted
11 Views

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.

Retired 12/31/2016

View solution in original post

0 Kudos
Highlighted
Beginner
10 Views

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?

0 Kudos
Highlighted
Black Belt
10 Views

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.)

 

0 Kudos
Highlighted
Beginner
10 Views

Everything works fine, thank you again!

0 Kudos
Highlighted
10 Views

Thanks, Ian, I forgot about the downcasing.

Retired 12/31/2016
0 Kudos