arraysfortranffifortran-iso-c-binding

Converting Fortran character and logical arrays between default and C-interoperable kinds


I am wrapping some legacy F77 code (that I cannot alter) in a C interface. Suppose the legacy code has

subroutine foo(s, l)
  character*10  s
  logical       l(10)
  …

I'm writing a small F2008 wrapper foo_wrapper that intends to expose a C-compatible interface through ISO_C_BINDING, do any necessary type conversions, call foo, and finally type-convert back again. My understanding is that I should start out with

subroutine foo_wrapper(c_s, c_l) bind(C, name="foo_wrapper")
  use ISO_C_BINDING, only: C_CHAR, C_BOOL
  character(kind=C_CHAR, len=1), dimension(10) :: c_s
  logical(kind=C_BOOL)                            c_l(10)
  …

but how do I actually do the conversion from c_s into a character*10, and likewise for c_l into a logical (and back after the call)?


Solution

  • Types with default kind parameters do not necessarily fail to be interoperable. Interoperability is based on the kind number, not the specific use of kind=c_kind, in the declaration. If the kind numbers (and if they have them, the length type parameters) match then the types are the same.

    Intrinsic assignment to a variable of intrinsic type of an expression of the same intrinsic type "converts" the kind type parameter as necessary.

    A copy-in/copy-out mechanism would be like

    <type>(kind=f_kind) f
    <type>(kind=c_kind) c
    
    c = f
    call foo(c)
    f = c
    

    where f and c can also be arrays of the same shape as each other.

    This always copies. If you want to be more fancy, you can use the techniques in an answer to a related question, using pointers, to copy only if the default and interoperable kinds are not the same.

    For real and integer intrinsic types, one may expect default kind parameters (or double precision for the real(kind=c_double)) to be the interoperable ones. Default logical is less likely to be interoperable: Fortran's default logical has the same storage size as default real which probably won't be what C's boolean type has.

    Characters also naturally may have interoperable default kind, but you also have to worry about the conversion between the scalar and the array. Again, the technique in the copy/associate linked answer handle this at the same time as the kind conversion.

    Consider the program

      use, intrinsic :: iso_c_binding
      implicit none
      
      print 1, "float", KIND(0e0)==c_float
      print 1, "double", KIND(0d0)==c_double
      print 1, "int", KIND(1)==c_int
      print 1, "char", KIND('')==c_char
      print 1, "bool", KIND(.TRUE.)==c_bool
    
    1 format (A,":",T10,L1)
    end program