How can I pass an array of C strings (char* cstrings[]
) to a Fortran
subroutine?
Question Arrays of strings in fortran-C bridges using iso_c_binding is definitely related, but the answer does not seem correct and does not even compile with GNU Fortran.
I am currently working on a C interface for a Fortran code, and I expected that iso_c_binding
(which I had used previously) would make this a piece of cake. No luck so far for arrays of C strings...
The Fortran subroutine should take an array of strings as an argument. In plain Fortran I would write something like the following:
subroutine print_fstring_array(fstring)
implicit none
character(len=*), dimension(:), intent(in) :: fstring
integer :: i
do i = 1, size(fstring)
write(*,*) trim(fstring(i))
end do
end subroutine print_fstring_array
One way to pass a single C string to Fortran is as C pointer (c_ptr
) (I know, I could also use an array of character(kind=c_char)
)
subroutine print_cstring(cstring) bind(C)
use iso_c_binding, only: c_ptr, c_f_pointer, c_loc, c_null_char
implicit none
type(c_ptr), target, intent(in) :: cstring
character(len=1024), pointer :: fstring
integer :: slen
call c_f_pointer(c_loc(cstring), fstring)
slen = index(fstring, c_null_char) - 1
write(*,*) fstring(1:slen)
end subroutine print_cstring
So, I assumed an array of c_ptr
would be a good idea
subroutine print_cstring_array(n, cstring) bind(C)
use iso_c_binding, only: c_ptr, c_int, c_f_pointer, c_loc, c_null_char
implicit none
integer(kind=c_int), intent(in) :: n
type(c_ptr), dimension(n), target, intent(in) :: cstring
character(len=1024), pointer :: fstr
integer :: slen, i
do i = 1, n
call c_f_pointer(c_loc(cstring(i)), fstring)
slen = index(fstring, c_null_char) - 1
write(*,*) fstring(1:slen)
end do
end subroutine print_cstring_array
but this produces a segmentation fault.
The C code for the last example is
# include "stdio.h"
# include "fstring.h"
void main(void) {
char* cstring[] = { "abc", "def", "ghi", "jkl" };
int n = 4;
print_cstring_array(&n, cstring);
}
and the contents of the header file fstring.h
are simply:
void print_cstring_array(int* n, char* cstring[]);
I am targeting GNU Fortran and Intel Fortran and have tested the above with GNU Fortran. The lengths of the strings is fixed (3 in the above example), in case this simplifies the solution. However, the dimension of the array can vary.
Any pointers (even C pointers) would be greatly appreciated.