I have the following test C library:
#include <stdlib.h>
struct mystruct {
int a;
double b;
};
struct mystruct *return_array_of_structs(int *size);
struct mystruct *return_array_of_structs(int *size) {
int i;
struct mystruct *ptr;
ptr = malloc(sizeof(struct mystruct)*10);
for(i=0; i<10; i++) {
ptr[i].a = i+1;
ptr[i].b = (i+1)*1.0L;
}
*size=10;
return ptr;
}
And the following module intended to be compiled with f2py
:
module test_c_lib
use iso_c_binding
implicit none
type :: t_mystruct
integer :: a
real(8) :: b
end type
contains
subroutine test()
use iso_c_binding
type(c_ptr) :: ret_c_ptr
integer :: length
! Interface to C function
interface
type(c_ptr) function c_return_array_of_structs(a) bind(C, name="return_array_of_structs")
import
integer(c_int) :: a
end function
end interface
! Call C function
ret_c_ptr = c_return_array_of_structs(length)
end subroutine
end module
The following makefile compiles this:
f_mod.so: f_mod.f90 c_lib.o
f2py -c f_mod.f90 c_lib.o -m f_mod
c_lib.o: c_lib.c
gcc -c -fpic c_lib.c -o c_lib.o
I can load the library in Python normally and execute the test()
subroutine without problems.
import f_mod
f_mod.test_c_lib.test()
But I do not how to convert ret_c_ptr
into an array of derived type t_mystruct
that I can normally operate as an array in Fortran. Any hint?
Note: the question is related to iso c bindings
and Fortran, not to f2py
or its integration with Python.
If you have a C pointer and want to associate a Fortran pointer with the target of that C pointer, you want to use c_f_pointer
to do that association. c_f_pointer
doesn't (generally) care whether the type is an intrinsic one or not, or scalar or not.
Let's define the Fortran derived type as an interoperable1 one:
type, bind(c) :: t_mystruct
integer(c_int) :: a
real(c_double) :: b
end type
and then have a Fortran pointer array of that type:
type(t_mystruct), pointer :: ptr_f(:)
With ptr_c
pointing to a suitable lump of memory we can do the association:
call c_f_pointer(ptr_c, ptr_f, [length])
to make ptr_f
an array of shape [length]
pointing to the C target.
1 Being interoperable isn't necessary, but it's certainly helpful to be if it can be.