I am trying to get Fortan API to work with the C code. The Fortran code contains mainly derived types which are NOT interoperable with the C by using iso_c_binding module. I have found this post
that contains similar problem https://software.intel.com/en-us/forums/topic/394312. This post c-fortran interoperability - derived types with pointers suggest that there is new standard that could solve this problem, but it is still not implemented by any fortran compiler. I have tried this code with gfortran 4.8.3 and gcc:
module types
type SomeDerivedType
integer :: someInteger
character*24 :: string
real, dimension(:), allocatable :: array
end type
end module
! Given the address of a C_PTR this subroutine allocates the memory required
! for a SomeDerivedType derived data type, initializes it with the given values,
! and stores the C_LOCated address in the C_PTR.
subroutine makeDerivedType_(cdt) bind(c, name='makeDerivedType_')
use iso_c_binding
use types
type (C_PTR) :: cdt
type (SomeDerivedType), pointer :: fdt
integer :: i
allocate(fdt)
allocate(fdt%array(0:10))
fdt%someInteger = 4
fdt%string = 'Hello'
do i = 0,9
fdt%array(i) = i*2.0
end do
cdt = C_LOC(fdt)
end subroutine makeDerivedType_
! This subroutine converts the given C_PTR value to a fortran pointer making
! it accessible again from fortran
subroutine examineDerivedType_(this) bind(c, name='examineDerivedType_')
use iso_c_binding
use types
type(C_PTR), value :: this
type(SomeDerivedType), pointer :: that
integer :: i
call C_F_POINTER(this,that)
write(*,*) "that%someInteger", that%someInteger
do i = 0,9
print*, "that%array:", that%array(i)
end do
end subroutine examineDerivedType_
The corresponding C code is:
#include<stdio.h>
extern void makeDerivedType_(void **m);
extern void examineDerivedType_( void *m );
typedef struct SomeDerivedType {
int someInteger;
char string[24];
double *array;
}SomeDerivedType;
int main(int argc, char **argv)
{
void *m = 0;
char *teststring[2] = {"test1", "test2"};
makeDerivedType_(&m);
SomeDerivedType* dt = (SomeDerivedType*) m;
for(int i = 0; i < 10; i++)
printf("%f\n",dt->array[i]);
printf("someInteger: %i\n",dt->someInteger);
printf("%s \n", dt->string);
examineDerivedType_(m);
}
This program returns:
2.000000
8192.001968
524288.126953
8388610.039062
67108880.375000
0.000000
0.000000
0.000000
0.000000
0.000000
someInteger: 4
Hello ?
that%someInteger 4
that%array: 0.00000000
that%array: 2.00000000
that%array: 4.00000000
that%array: 6.00000000
that%array: 8.00000000
that%array: 10.0000000
that%array: 12.0000000
that%array: 14.0000000
that%array: 16.0000000
that%array: 18.0000000
It is interesting to see that string and someInteger variables are properly returned from C,
while array returns bad values. I assumed that the reason is that array is not contiguously allocated in Fortran code so C returns contiguous memory locations starting from *(array+i). Is it possible to ensure that Fortran allocates array contiguously or exists any other more portable way to access derived type with allocatable components from C.