According to the rules of the current Fortran (Fortran 2008, but this is the same for when C-compatibility was introduced in Fortran 2003), the Fortran procedure is not C-compatible if it has the supposed argument of a fictitious figure (other restrictions apply). In your degC code degC dummy argument to the DegCtoF function declared as
real(c_double), intent(in), dimension(:) :: degC
- such a thing.
So, in F2003 you cannot have such interoperability. This is where things get tricky.
In the proposed project for F2015 (based on ISO TS29113 Further Fortran compatibility with C ), such a thing is compatible. And this syntax (I think) is supported by the latest versions of gcc, so the code is not rejected by gfortran.
(TS) The standard interaction with such a procedure with an assumed form argument requires, however, the use of the C descriptor described in ISO_Fortran_binding.h on the C side, which is not implemented in gcc. Such interaction instead requires understanding the gcc array descriptor directly.
But you are lucky. In your case, you do not need to use the argument of the alleged figure: you can use the explicit argument of the dummy figure, and this interaction is part of F2003. All you have to do is pass the size of the array.
In any case, the compatible function should return a scalar result, so you also need to go to the subroutine, as indicated in innoSPG's answer.
Finally, I mentioned your use
real(c_double), bind(c) :: degF, degC
in the module.
These are interoperable global variables (through association associations). You do not reference these variables in Fortran code: the dummy and function result are not these things.
In this simple case, from the above and in another answer, you will have a subroutine like
subroutine DegCtoF(n, degC, degF) bind(c,name='DegCtoF') ... end subroutine
but this is perhaps a good opportunity to describe the use of the C descriptor from ISO_Fortran_binding.h . Please note, however, that in the near future gfortran does not support this approach.
Consider the source of Fortran
subroutine DegCtoF(degC, degF) bind(c,name='DegCtoF') use, intrinsic :: iso_c_binding, only : c_double implicit none real(c_double), intent(in), dimension(:) :: degC real(c_double), intent(out), dimension(*) :: degF degF(1:SIZE(degC)) = degC*1.8+32 end subroutine DegCtoF
(for simplicity, I assume that degF memory degF is done on the C side - naturally, you can go beyond the intended size array). For this routine to be interoperable, the argument corresponding to degC must be a pointer to CFI_cdesc_t .
Take the C code (with magic size numbers)
#include "ISO_Fortran_binding.h" #include <stdio.h> void DegCtoF(CFI_cdesc_t*, double*); int main(int argc, char *argv[]) { printf("C and Fortran together!\n"); CFI_CDESC_T(1) DegreesC_Fdesc; CFI_index_t extent[1] = {2}; CFI_rank_t rank = 1; double DegreesC[2] = {32, 64}; double DegreesF[2]; CFI_establish((CFI_cdesc_t*)&DegreesC_Fdesc, &DegreesC, CFI_attribute_other, CFI_type_double, 2*sizeof(double), rank, extent); DegCtoF((CFI_cdesc_t*)&DegreesC_Fdesc, DegreesF); printf("%3.1f [C] = %3.1f [F]\n", DegreesC[0], DegreesF[0] ); printf("%3.1f [C] = %3.1f [F]\n", DegreesC[1], DegreesF[1] ); return 0; }
Here CFI_establish sets a suitable C DegreesC_Fdesc descriptor, which may correspond to the intended argument of the Fortran argument. Inside the Fortran routine, there is no problem evaluating the size of the incoming array.