Is it possible to create an interoperable types in Fortran 2003?
I fairly sure that pointers and allocatable are not allowed in bind(c) derived types. I also don’t think you can have other derived types either since each component of a derived type must ne an ISO_C_BINDING interoperable type. Though, I’ll ask when I’m back in the office on Monday since I’m not positive.
This was a good exercise for me since I haven’t had the opportunity to work with ISO_C_BINDING. I was correct in that you can’t have derived type pointers but you can use regular C_PTR types and then use the function “c_f_pointer” to associate the C pointer with a local pointer to the derived type.
subroutine fortran_func (Aptr, N)
use iso_c_binding
type, bind(c) :: type2_t
integer(c_int) :: idx, size
end type type2_t
type, bind(c) :: type3_t
integer(c_int) :: idx, size
end type type3_t
type, bind(c) :: type1_t
type(type2_t) :: params
type(c_ptr) :: status
integer(c_int) :: idx
end type type1_t
type(c_ptr), value :: Aptr
type(type1_t), pointer :: A
type(type3_t), dimension(:), pointer :: status
integer, value :: N
integer :: i
! Assocatate the C "Aptr" pointer to a local fortran
! pointer to type1_t
call c_f_pointer(Aptr,A)
A%idx = 1
A%params%idx = 100
A%params%size = 1000
! Associate the 'status' type1_t pointer to A%status
! You must add a shape arguement (N) since its an array
call c_f_pointer(A%status,status,N)
do i=1,N
status(i)%idx = i
status(i)%size = N-i
enddo
end subroutine fortran_func
module type_mod
use iso_c_binding
type, bind(c) :: type2_t
integer(c_int) :: idx, size
end type type2_t
type, bind(c) :: type3_t
integer(c_int) :: idx, size
end type type3_t
type, bind(c) :: type1_t
type(type2_t) :: params
type(c_ptr) :: status
integer(c_int) :: idx
end type type1_t
end module type_mod
program test_f_to_c
use iso_c_binding
use type_mod
interface
subroutine init_data(A,N) bind(c)
use iso_c_binding
use type_mod
type(type1_t) :: A
integer(c_int), value :: N
end subroutine init_data
end interface
integer, value :: N
parameter(N=10)
type(type1_t) :: A
integer :: i
type(type3_t), dimension(:), pointer :: status
call init_data(A,N)
print *, A%idx, A%params%idx, A%params%size
call c_f_pointer(A%status,status,N)
do i=1,N
print *, i, status(i)%idx, status(i)%size
enddo
end program test_f_to_c
init.c
#include <stdio.h>
#include <malloc.h>
typedef struct TYPE3_T {
int idx;
int size;
} type3_t;
typedef struct TYPE2_T {
int idx;
int size;
} type2_t;
typedef struct TYPE1_T {
type2_t params;
type3_t *status;
int idx;
} type1_t;
void init_data(type1_t * A, int N) {
A->idx = 1;
A->params.idx = 10;
A->params.size = 100;
A->status = (type3_t*) malloc(sizeof(type3_t) * N);
for (int i=0; i<N; ++i) {
A->status[i].idx = i+1;
A->status[i].size = N-i;
}
}