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