函数指针的gfortran -fc-prototypes选项

问题描述

gfortran编译器具有interoperability option -fc-prototypes,可为可互操作的函数(具有BIND(C)属性生成正确的C-prototype。

链接中写道:“对于函数指针,将生成一个指向返回int且没有显式参数列表的函数的指针。”

我用一些包含BIND(C)子例程的代码进行了尝试,该子例程将函数指针指向带有2个整数参数的子例程。在文件test.F95获取Fortran代码

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),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

编译为:gfortran test.F95 -c -Wall -fc-prototypes > proto.h

这将生成具有以下内容的C头文件proto.h

#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

如您所见,抽象接口中子例程fproto的原型是正确的。但是test子例程的参数(即函数指针)的正确C原型应为:

void (*pf)(int,int)

但是gfortran会生成

int (*pf)()

这根本不匹配。这有什么意义呢?这是否意味着我应该始终将函数指针传递给返回int的函数?还是这只是(故意地?)产生了错误

解决方法

gfortran正在按设计和文档的方式工作(在第二段的问题中引用了相关的文档!)。

子例程测试将通用C函数指针作为参数。从该子例程的接口的互操作性的角度来看,可以传入任何函数。gfortran对任何函数的匹配函数的解释是“指向没有返回明确参数列表的int的函数的指针”。

Fortran过程指针与函数指针的关联是执行时间活动。该原型描述了函数的特性,这是一个编译时概念。