Reputation: 67
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?
Upvotes: 1
Views: 208
Reputation: 21431
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.
Upvotes: 2