Mokus
Mokus

Reputation: 10410

Exchanging array between Fortran and C

I have the following C and Fortran code where I would like to exchange some data

FUNCTION exchange_data(data) bind(c,name='exchange_data')
    use iso_c_binding
    integer(kind=c_int)                                 :: exchange_data
    real(kind=c_double), intent(inout), dimension(*)    :: data

END FUNCTION exchange_data

....

WRITE(*,*), "Sent data to C"
DO I=1,NumBl
    DO J=1,WindSpeedCoordNr
        WRITE(*, FMT2), GLOBAL_COORD_ALONG_BEAM(I, J, :)
    END DO
END DO
cflag = exchange_data(GLOBAL_COORD_ALONG_BEAM)

WRITE(*,*), "Received data from C"
DO I=1,NumBl
    DO J=1,WindSpeedCoordNr
        WRITE(*, FMT2), GLOBAL_COORD_ALONG_BEAM(I, J, :)
    END DO
END DO

And the following test C code:

int exchange_data(double* positions)
{

    printf("Received data from Fortran");
    bladepositions = positions;
    for (int i = 0; i < numbld; i++) {
        for (int j = 0; j < datapointnr; j++) {
            printf("[");
            for (int k = 0; k < 3; k++) {

                printf("%5.4f ", bladepositions[3 * datapointnr * k + 3 * j + i]);
                windspeedalongblade[3 * datapointnr * k + 3 * j + i] = 1.0;
            }
            printf("]\r\n");
        }
    }


    positions = windspeedalongblade;

    printf("Data will be send from C");
    for (int i = 0; i < numbld; i++) {
        for (int j = 0; j < datapointnr; j++) {
            printf("[");
            for (int k = 0; k < 3; k++) {
                printf("%5.4f ", positions[3 * datapointnr * k + 3 * j + i]);
            }
            printf("]\r\n");
        }
    }
    return 0;
}

This has the following output

Sent data to C
  -18.6593  -29.1175  137.0735
  -18.8588  -29.1308  137.0803
  -19.0582  -29.1441  137.0871

Received data from Fortran
[-18.6593 -29.1175 137.0735 ]
[-18.8588 -29.1308 137.0803 ]
[-19.0582 -29.1441 137.0871 ]

Data will be send from C
[1.0000 1.0000 1.0000 ]
[1.0000 1.0000 1.0000 ]
[1.0000 1.0000 1.0000 ]

Received data from C
  -18.6593  -29.1175  137.0735
  -18.8588  -29.1308  137.0803
  -19.0582  -29.1441  137.0871

I seems I can transfer data to the C function but not back to Fortran code. How can I achieve that?

Upvotes: 3

Views: 188

Answers (1)

Claudiu
Claudiu

Reputation: 2164

The problem is that the following line:

positions = windspeedalongblade;

doesn't permanently assign windspeedalongblade to positions (see here the difference between passing by value and by reference).

To do that you would need for positions to be passed as a pointer to the array:

int exchange_data(double** positions)
{
    ...
    *positions = windspeedalongblade;
    printf("Data will be send from C");
    for (int i = 0; i < numbld; i++) {
        for (int j = 0; j < datapointnr; j++) {
            printf("[");
            for (int k = 0; k < 3; k++) {
                printf("%5.4f ", *positions[3 * datapointnr * k + 3 * j + i]);
        }
            printf("]\r\n");
        }
    }
    return 0;
}

But in this case you have to be sure that windspeedalongblade remains persistent until you get to use positions.

The simpler solution is to leave the function as it is and assign the values of the positions array directly:

int exchange_data(double* positions)
{

    printf("Received data from Fortran");
    bladepositions = positions;
    for (int i = 0; i < numbld; i++) {
        for (int j = 0; j < datapointnr; j++) {
            printf("[");
            for (int k = 0; k < 3; k++) {

                printf("%5.4f ", bladepositions[3 * datapointnr * k + 3 * j + i]);
                windspeedalongblade[3 * datapointnr * k + 3 * j + i] = positions[3 * datapointnr * k + 3 * j + i] = 1.0;
            }
            printf("]\r\n");
        }
    }

    printf("Data will be send from C");
    for (int i = 0; i < numbld; i++) {
        for (int j = 0; j < datapointnr; j++) {
            printf("[");
            for (int k = 0; k < 3; k++) {
                printf("%5.4f ", positions[3 * datapointnr * k + 3 * j + i]);
            }
            printf("]\r\n");
        }
    }
    return 0;
}

So in the end it depends whether you want positions to be an array or just a pointer to an array. From the looks of the Fortran code it seems that it is an array, in which case the second solution would be best.

Upvotes: 4

Related Questions