1

In Fortran I have a an array specified as:

dimension insv(*)

Now I would like to edit this array from C. I managed to read the array from C by using the iso_c_binding:

  SUBROUTINE userroutine(insv)
  IMPLICIT NONE
  INTERFACE
  SUBROUTINE MODIFYARRAY(insv) BIND(C)
  USE, INTRINSIC::ISO_C_BINDING
     REAL(C_DOUBLE),DIMENSION(*), INTENT(INOUT) :: insv
  END SUBROUTINE MODIFYARRAY
  END INTERFACE

  dimension insv(*)

  WRITE(insv(0))
  call modifyarray(insv)
  WRITE(insv(0))
  END

My C function:

__declspec(dllexport) void modifyarray(double * insv)

But modifying a value in this array in C either crashes or simply doesnt get changed at all.

__declspec(dllexport) void modifyarray(double * insv)
{
    insv[0] = 1234.00;
}

Im not sure as to what i should change to the iso_c_binding or the C function to make this work.

Some more context: The fortran array type cannot be changed since the dimension variable is a parameter of a userroutine, not in my control, so to say. The array is already filled when entering the fortran function, but needs to be modified in C.

10
  • Please show the code. Especially the whole C function. See minimal reproducible example. And how you call it in Fortran - including variable declarations. We must know where does the array originally come from. Commented Jun 15, 2017 at 9:09
  • Unless you have some other implicit typing rule in force insv is an integer array. The subroutine is expecting a real argument. Commented Jun 15, 2017 at 9:32
  • Changing it to INTEGER(C_INT),DIMENSION(*) gives me the following error: The type of the actual argument differs from the type of the dummy argument. I also changed the C function's parameter to: int * insv Commented Jun 15, 2017 at 9:46
  • Show the complete code. Including implicit none and including all variable declarations. Commented Jun 15, 2017 at 10:58
  • 1
    The subroutine as you posted it now is not legal Fortran. It will not compile. Test the code before pasting it here! It must be compilable and it must reproduce the problem. Reading minimal reproducible example is essential. Commented Jun 15, 2017 at 13:11

1 Answer 1

3

Assuming that:

  • insv is an array of real(C_DOUBLE)
  • you want to write insv (not to a file unit defined by insv as it seems now)
  • the calling program defines insv as an array of 10 components

a possible working test case follows:

Fortran:

SUBROUTINE userroutine(insv)
    USE, INTRINSIC::ISO_C_BINDING
    IMPLICIT NONE
    INTERFACE
        SUBROUTINE MODIFYARRAY(insv) BIND(C)
            USE, INTRINSIC::ISO_C_BINDING
            REAL(C_DOUBLE),DIMENSION(*), INTENT(INOUT) :: insv
        END SUBROUTINE MODIFYARRAY
    END INTERFACE

    real(C_DOUBLE), dimension(*) :: insv

    WRITE(*,*) insv(1)
    call modifyarray(insv)
    WRITE(*,*) insv(1)
END

PROGRAM MAIN
    USE, INTRINSIC::ISO_C_BINDING
    real(C_DOUBLE) :: insv(10)
    insv = 2.d0
    call userroutine(insv)
END

C:

void modifyarray(double * insv)
{   
    insv[0] = 1234.00;
}   
Sign up to request clarification or add additional context in comments.

2 Comments

Hello Franz, your test case has given me insight to what the problem appeared to be. In Fortran the index of an array starts at 1 whereas C starts at 0. I was changing the wrong index on the C side. Thank you very much.
On the Fortran side, not C side. At least in the incomplete code you show.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.