The gfortran compiler has the interoperability option -fc-prototypes which generates the correct C-prototypes for interoperable functions (which have the BIND(C) attribute).
In the link it is written: "For function pointers, a pointer to a function returning int without an explicit argument list is generated. "
I tried it with some code that contains a BIND(C) subroutine that takes a function pointer to a subroutine with 2 integer arguments. Take the Fortran code in file test.F95
:
subroutine test(pf) bind(c)
use, intrinsic :: iso_c_binding
implicit none
type(c_funptr), intent(in), value :: pf
abstract interface
subroutine fproto(x, y) bind(c)
use iso_c_binding, only: c_int
integer(c_int), intent(in), value :: x, y
end subroutine fproto
end interface
procedure(fproto), pointer :: f
call c_f_procpointer(pf, f)
call f(1, 2)
end subroutine test
Compile with: gfortran test.F95 -c -Wall -fc-prototypes > proto.h
This generates the C header file proto.h
with the content:
#include <stddef.h>
#ifdef __cplusplus
#include <complex>
#define __GFORTRAN_FLOAT_COMPLEX std::complex<float>
#define __GFORTRAN_DOUBLE_COMPLEX std::complex<double>
#define __GFORTRAN_LONG_DOUBLE_COMPLEX std::complex<long double>
extern "C" {
#else
#define __GFORTRAN_FLOAT_COMPLEX float _Complex
#define __GFORTRAN_DOUBLE_COMPLEX double _Complex
#define __GFORTRAN_LONG_DOUBLE_COMPLEX long double _Complex
#endif
void f ();
void fproto (int x, int y);
void test (int (*pf)());
#ifdef __cplusplus
}
#endif
As you can see, the prototype of the subroutine fproto
in the abstract interface is correct. But the correct C prototype of the argument of the test
subroutine, i.e. of the function pointer should be:
void (*pf)(int, int)
But gfortran generates
int (*pf)()
This does not match at all. What is the point of this? Does that mean I should always pass function pointers to functions that return int? Or is this just (intentionally?) generated wrong?
gfortran is working as designed and documented (with the relevant piece of documentation actually quoted in the question in paragraph two!) here.
The subroutine test takes a generic C function pointer as an argument. From the perspective of interoperability of that subroutine's interface, any function can be passed in. gfortran's interpretation of a matching function for any function is "a pointer to a function returning int without an explicit argument list".
The association of a Fortran procedure pointer with the function pointer is an execution time activity. The prototype describes the characteristics of the function, which is a compile time concept.