C Interoperability: Logical types and C_LOC
Rafik_Zurob 270003B2DK Visits (4333)
C interoperability is one of the most popular features of Fortran 2003. Recently, I was part of a discussion about why XL Fortran flags the following as invalid:
use iso_c_binding type(c_ptr) p logical(8), target :: logicalarray(20) p = c_loc(logicalarray) ! XLF will flag an error here end
According to Fortran 2003 (and Fortran 2008), the argument to the C_LOC function must either be of an interoperable type or must be a nonpolymorphic scalar. The standard tries to be interoprable with the _Bool type in C, which is of size 1. So the only interoperable logical type is logical(C_BOOL), which is the same as logical(1).
We can get rid of the error in the program above, and make it F2003-compliant, by using the C_BOOL kind from ISO_C_BINDING. i.e.
use iso_c_binding type(c_ptr) p logical(c_bool), target :: logicalarray(20) p = c_loc(logicalarray) ! OK end
But what if you want to pass a logical(8) array to a C program anyway? If you're willing to part with portability, you can do so by specifying the following compiler options: -qintlog -qport=clogicals. The -qintlog option tells the compiler to treat logicals as integers. Since integer(8) is interoperable, the compiler will not flag the call to C_LOC. The -qport=clogicals option changes XL Fortran's representation of
There is another workaround that does not require -qintlog: Use C_LOC to take the address of the first element of the array. i.e.
use iso_c_binding type(c_ptr) p logical(c_bool), target :: logicalarray(20) p = c_lo
This workaround still requires -qport=clogicals, however, to get logical values other than 1 and 0 to have the same meaning in Fortran and C.
I prefer the C_BOOL way, however. After all, the C interoperability part of the Fortran standard is intended to provide a portable way of mixing code written in Fortran and C.