The C declaration char *argv[]
is array of pointer to char. The equivalent Fortran argument declaration is TYPE(C_PTR) :: argv(*)
, where each element in the array is the C address of a character of C kind.
The usual C convention is that the character is actually the first character in an array of character (i.e. you have the C address of an array of character of C kind), and the length of that array of char is null terminated (i.e. all up you have an array of pointers to C strings). The comment in your C code also indicates that the size of the array of pointers is indicated by a final array element of NULL. This is consistent with the conventions around argv
arguments in C.
To be able to find the C address of an object in Fortran, the object must have the TARGET attribute. The results of evaluating an expression does not have the target attribute.
As written, the bar
subroutine has no idea about the size of the argv
dummy array (it is an assumed size argument). However, if the argv
dummy argument was perhaps assumed shape, you could do something like:
SUBROUTINE bar(argv)
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_LOC, C_CHAR, C_INT, &
C_NULL_CHAR, C_NULL_PTR
! The input to bar (?) that needs to be converted for use in the C function.
CHARACTER(*), INTENT(IN) :: argv(:)
! The array of C pointers.
TYPE(C_PTR) :: argv_c(SIZE(argv) + 1)
! A local type to simplify memory management.
TYPE string
CHARACTER(LEN=:,KIND=C_CHAR), ALLOCATABLE :: item
END TYPE string
! Temporary arrays of character. Need to have TARGET for C_LOC.
TYPE(string), TARGET :: tmp(SIZE(argv))
! Utility index.
INTEGER :: i
! The interface for the C function
INTERFACE
FUNCTION foo(argv) BIND(C, NAME='foo')
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT
IMPLICIT NONE
! INTENT(IN) here assuming foo doesn't modify the array of pointers.
TYPE(C_PTR), INTENT(IN) :: argv(*)
INTEGER(C_INT) :: foo
END FUNCTION foo
END INTERFACE
INTEGER(C_INT) :: ierror
DO i = 1, SIZE(argv)
! This may involve kind conversion.
tmp(i)%item = TRIM(argv(i)) // C_NULL_CHAR
argv_c(i) = C_LOC(tmp(i)%item)
END DO
! Size of the argv array on the C side indicated by a NULL.
argv_c(SIZE(argv_c)) = C_NULL_PTR
ierror = foo(argv_c)
...
! memory allocated for the components of the tmp object (and hence
! the things pointed at by the argv_c array) will go away when this
! subroutine terminates.
END SUBROUTINE bar