Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The ABI of the compilers can differ. You should not pass the structures directly, but build them inside the subroutines and use pointers, which you should pass as <code>type(c_ptr)</code> or as assumed size arrays (but a copy can happen then!).</p> <p>The interoperability with C from Fortran 2003 is not meant only to interact with C but any other compiler interoperable with C. It can be a diferent Fortran compiler.</p> <p>Be aware it is against the rules of Fortran to declare the same type in more places and use it as the same type, unless the type is <code>sequence</code> or <code>bind(C)</code>. This is another reason why your program is not standard conforming.</p> <p>called.f90:</p> <pre><code>subroutine offload(cl_c) use iso_c_binding type, bind(C) :: cell_C integer :: id integer :: na, nb, nc type(c_ptr) :: a,b,c end type cell_C type cell integer :: id real, pointer :: a(:) real, pointer :: b(:) real, pointer :: c(:) end type cell type(cell) :: cl type(cell_C) :: cl_C integer :: n cl%id = cl_C%id call c_f_pointer(cl_C%a, cl%a, [cl_c%na]) call c_f_pointer(cl_C%b, cl%b, [cl_c%nb]) call c_f_pointer(cl_C%c, cl%c, [cl_c%nc]) print *, cl%a(1:10) print *, cl%b(1:10) end subroutine offload </code></pre> <p>caller.f90:</p> <pre><code>program caller use iso_c_binding type, bind(C) :: cell_C integer :: id integer :: na, nb, nc type(c_ptr) :: a,b,c end type cell_C type cell integer :: id real, allocatable :: a(:) real, allocatable :: b(:) real, allocatable :: c(:) end type cell integer :: n,i,j type(cell),target :: cl(2) type(cell_c) :: cl_c n=10 do i=1,2 allocate(cl(i)%a(n)) allocate(cl(i)%b(n)) allocate(cl(i)%c(n)) end do do j=1, 2 do i=1, n cl(j)%a(i)=10*j+i cl(j)%b(i)=10*i+j end do end do cl_c%a = c_loc(cl(1)%a) cl_c%b = c_loc(cl(1)%b) cl_c%c = c_loc(cl(1)%c) cl_c%na = size(cl(1)%a) cl_c%nb = size(cl(1)%b) cl_c%nc = size(cl(1)%c) cl_c%id = cl(1)%id call offload(cl_c) print *, cl(1)%c end program caller </code></pre> <p>with gfortran and ifort:</p> <pre><code>&gt;gfortran called.f90 -c -o called.o &gt;ifort caller.f90 -c -o caller.o &gt;ifort -o a.out called.o caller.o -lgfortran &gt;./a.out 11.0000000 12.0000000 13.0000000 14.0000000 15.0000000 16.0000000 17.0000000 18.0000000 19.0000000 20.0000000 11.0000000 21.0000000 31.0000000 41.0000000 51.0000000 61.0000000 71.0000000 81.0000000 91.0000000 101.000000 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 </code></pre> <p>No dynamic libraries necessary here.</p> <p>For 100% theoretical portability one could use <code>c_int</code>, <code>c_float</code>,... the formatting could be better and so on, but you get the point.</p> <p>You can also overload the assignments between <code>cell</code> and <code>cell_C</code> to ease the conversion.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload