I am trying to pass an array of strings from C to a Fortran subroutine as well as from Fortran to that same Fortran subroutine. I have managed to pass single strings (i.e. 1D character arrays) successfully from both C and Fortran. However, I'm having trouble with arrays of strings. I am using ISO C binding on the Fortran side, and ideally I'd like this to be as seamless as possible on the calling side.
I have read some related questions and answers. Some, (i.e. this and this) are simply "Use ISO C" without further details, which doesn't help much. This answer was very helpful (similar answer to a different question), but only works for single strings, where it seems that the c_null_char is recognized in the single Fortran string. I can't figure out what to do for the array case without having two separate routines.
What I currently have is a C routine which I want to pass the array of strings (string
) from:
#include <iostream>
extern "C" void print_hi_array(char input_string[][255]);
using namespace std;
int main() {
char string[3][255] = {"asdf","ghji","zxcv"};
print_hi_array(string);
return 0;
}
And, a similar Fortran routine:
program main
implicit none
call print_hi_array( (/"asdf", "ghji", "zxcv"/) )
end program
Thus far, this is what I have for the receiving end:
subroutine print_hi_array(input_string) bind(C)
use iso_c_binding, only: C_CHAR, c_null_char
implicit none
character (kind=c_char, len=1), dimension (3,255), intent (in) :: input_string
character (len=255), dimension (3) :: regular_string
character (len=255) :: dummy_string
integer :: i,j,k
write (*,*) input_string
do j = 1 , 3
dummy_string(:) = c_null_char
k = 1
do i = 1 + (j-1)*255, j*255,1
if (input_string(i) .ne. c_null_char) then
write (*,*) "i ",i,j, input_string(i)
dummy_string(k:k) = input_string(i)
endif
k = k +1
enddo
regular_string(j) = dummy_string
enddo
write (*,*) regular_string
end subroutine print_hi_array
This works for the C function; I get this output:
asdfghjizxcv
j= 1
i 1 1 a
i 2 1 s
i 3 1 d
i 4 1 f
j= 2
i 256 2 g
i 257 2 h
i 258 2 j
i 259 2 i
j= 3
i 511 3 z
i 512 3 x
i 513 3 c
i 514 3 v
asdf ghji zxcv
However, when it's done through Fortran I get nonsense out:
asdfghjizxcv@O,B�@(P,B�]B]6(P,B�@ .......
It seems there is no c_null_char
in this approach.
So, how can I write a Fortran subroutine to take in arrays of strings from both C and Fortran?