I am writing Fortran code to save data to the HDF5 file format. In all the examples provided with HDF5 that I looked at, I couldn't help but notice the use of the C_LOC(x) intrinsic function with variables x that violate or might violate the Fortran Standard (§18.2.3.7 and §18.3.4). I picked out one example (compound_fortran2003.f90) and provide a small snippet of it:
TYPE s1_t
CHARACTER(LEN=1), DIMENSION(1:13) :: chr
INTEGER(KIND=SELECTED_INT_KIND(1)) :: a
REAL(KIND=SELECTED_REAL_KIND(5)) :: b
REAL(KIND=SELECTED_REAL_KIND(10)) :: c
END TYPE s1_t
TYPE(s1_t), TARGET :: s1(10)
TYPE(C_PTR) :: f_ptr
...
f_ptr = C_LOC(s1(1))
In my mind, f_ptr = C_LOC(s1(1)) is used here in a non-compliant way because:
- The derived data type does not have the
BIND(C)attribute; - The derived data type components are not necessarily of an interoperable type kind parameter (they might match the type kind parameter of one of the interoperable types but there is no guarantee). Related post: How to check that fortran real is compatible with C float?
Hence, how much can the interoperability requirements be loosened when working with HDF5 as the HDF5 examples themselves do not strictly adhere to the Fortran Standard interoperability requirements?
EDIT:
- Regarding the argument
XofC_LOC(X), the standard states "X shall have either the POINTER or TARGET attribute. It shall not be a coindexed object. It shall be a variable with interoperable type and kind type parameters, an assumed-type variable, or a nonpolymorphic variable that has no length type parameter. If it is allocatable, it shall be allocated. If it is a pointer, it shall be associated. If it is an array, it shall be contiguous and have nonzero size. It shall not be a zero-length string". - Regarding a derived data type, the standard states "A derived type is interoperable with a C structure type if and only if the derived type has the BIND attribute [...]".
C_LOC(s1(1))is non-compliant because of (1) and (2)? The actual argument toC_LOCdoesn't need to be interoperable.C_LOCprovides an opaque "handle" for it. In an actual implementation, this handle might be the C address of the argument; however, only a C function that treats it as a void (generic) C pointer that cannot be dereferenced (ISO/IEC 9899:2018, 6.5.3.2) is likely to be portable".f_ptr = C_LOC(s1(1))is the part that violates the requirements of Fortran: you now even remark that the argument can be "a nonpolymorphic variable that has no length type parameter" (whichs1(1)is).s1(1)is a scalar.