Let’s say one have a Fortran library with some routines that have allocatable arrays as dummy arguments, and one want to pass data in these arguments from C. Constraints: the library must not be modified, and the data must not be duplicated.
It looks to me that C descriptors are needed here… I am not used to them, and I wrote a toy example:
Fortran side:
module somemodule
implicit none
contains
subroutine frout(a)
double precision, allocatable, intent(in) :: a(:)
write(*,*) lbound(a), size(a), ubound(a)
write(*,*) a(:)
end
end module
! assuming one doesn't want to add the C binding features in
! the original module, a wrapper routine is needed
subroutine frout_wrap(a) bind(C)
use, intrinsic :: iso_c_binding
use somemodule
real(c_double), allocatable, intent(in) :: a(:)
call frout(a)
end subroutine
C side:
#include <stdlib.h>
#include <ISO_Fortran_binding.h>
void* frout_wrap(CFI_cdesc_t*);
int main()
{
double* mydata = (double*)malloc(6*sizeof(double));
for (int i=0; i<6; i++) mydata[i] = (double)i;
CFI_cdesc_t mycfi;
mycfi.base_addr = (void*)mydata;
mycfi.elem_len = sizeof(double);
mycfi.attribute = CFI_attribute_allocatable;
mycfi.rank = 1;
mycfi.type = CFI_type_double;
mycfi.dim[0].lower_bound = -2;
mycfi.dim[0].extent = 6;
mycfi.dim[0].sm = sizeof(double);
frout_wrap(&mycfi);
}
It works, I get the expected output:
ifort -c cfinteropf.f90 ; icc cfinterop.c cfinteropf.o -lifcore -static && a.out
-2 6 3
0.000000000000000E+000 1.00000000000000 2.00000000000000
3.00000000000000 4.00000000000000 5.00000000000000
However, is it the right way (by hand) to build the descriptor? I’ve seen the routine CFI_establish()
that seems dedicated to that, but couldn’t get a working example with it…