I would like to create a fortran binding to a C function that returns an arbitrary length string as a function argument. I have read this similar question, but I simply cannot get the solution there to work. I have simplified the problem as much as I can so I can explain here.
I have a C function like this: c_string.c (I know that usually this kind of function would also have an argument that also returns the length of the string, but I have left it out here for simplicity, since in this example I know the length.)
#include <string.h>
void make_string(char *string) {
strcpy(string, "sand");
}
It seems to work fine in a C program, for example:
#include <stdlib.h>
#include <stdio.h>
#include "c_string.c"
int main() {
char *string;
string = malloc(5*sizeof(char));
make_string(string);
printf(string);
}
I want to call this function in a Fortran program: main.f90. So I make a c binding following the solution mentioned above.
program main
use iso_c_binding
implicit none
interface
subroutine c_make_string(string) bind (C, name='make_string')
import
type (c_ptr), value :: string
end subroutine c_make_string
end interface
type (c_ptr) :: c_string
character, pointer :: local_string(:)
call c_make_string(c_string)
call c_f_pointer(c_string, local_string, [4])
write (*,*) local_string
end program main
But this program results is a segfault at the write statement. Trying to access the resulting local_string
pointer by indexing gives a segfault too.
Note: after adding the value attribute to the interface, the segfault is now in the C function.
The only solution I came up with is to not use c_ptr
and c_f_pointer()
, and just use a maximum buffer length like 512.
program main
use iso_c_binding
implicit none
interface
subroutine c_make_string(string) bind (C, name='make_string')
import
character (len=1, kind=c_char) :: string(512)
end subroutine
end interface
character (len=1, kind=c_char) :: local_string(512)
call c_make_string(local_string)
write (*,*) local_string
end program main
But that results in a whole bunch of junk after the useful data in the string. Of course, that is easily worked around if you know the length of the intended string, but it feels unsatisfactory to me... if only I knew what was going wrong with the c_f_pointer()
call in the original solution. Should I allocate space for the local_string
before, as I do in the C program? But how? Why does it seem I need fixed length arrays for the binding? What is the clean solution to passing char * variables of arbitrary length via subroutine/function arguments?