Python/Fortran interoperability
sturlamolden
sturlamolden at yahoo.no
Sun Aug 23 21:28:24 EDT 2009
On 24 Aug, 01:59, sturlamolden <sturlamol... at yahoo.no> wrote:
> subroutine foobar(cstr) bind(c, name='foobar')
> use, intrinsic :: iso_c_binding
> type(c_ptr) :: cstr
> character(*), pointer :: fstr
> call c_f_pointer(cptr, fptr)
Actually, this does not work, as it is illegal to create a pointer to
a character(*). However, we can create a pointer to a huge string (say
2 GB or whatever maximum the system allows), and slice that down to a
substring using strlen to obtain the length. So here is how to pass a
variable-length string from C to Fortran, tested with gcc and gfortran
4.1.1.
In foobar.f03:
subroutine wrap_foobar(cstr) bind(c, name='foobar')
! a wrapper for foobar we expose to C
use, intrinsic :: iso_c_binding
interface
function strlen(cstr) bind(c, name='strlen')
use, intrinsic :: iso_c_binding
integer(c_int) :: strlen
type(c_ptr), value :: cstr
end function strlen
end interface
type(c_ptr), value :: cstr
character(2147483647), pointer :: p_fstr
integer :: n
n = strlen(cstr)
call c_f_pointer(cstr, p_fstr)
call foobar(p_fstr(1:n))
end subroutine
subroutine foobar(fstr)
! this is the Fortran function we want to call from C
! it takes a variable length string as argument and print its
length
character(*) :: fstr
write (*,*) len(fstr)
end subroutine
In main.c:
extern void foobar(char *);
int main(int argc, char *argv[])
{
foobar(argv[1]);
return 0;
}
Sturla at STURLA-PC /d/fortrantest
$ gfortran -c foobar.f03
Sturla at STURLA-PC /d/fortrantest
$ gcc -c main.c
Sturla at STURLA-PC /d/fortrantest
$ gcc -o test.exe main.o foobar.o -lgfortran
Sturla at STURLA-PC /d/fortrantest
$ ./test 1234
4
Sturla at STURLA-PC /d/fortrantest
$ ./test 0123456789
10
So it works...
Regards,
Sturla Molden
More information about the Python-list
mailing list