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)?
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