函数指针的 gfortran -fc-prototypes 选项
gfortran -fc-prototypes option for function pointers
gfortran 编译器具有 interoperability option -fc-prototypes,它为可互操作的函数(具有 BIND(C) 属性)生成正确的 C 原型。
在 link 中写道:“对于函数指针,生成一个指向函数 returning 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), 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
编译为: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)()
这根本不匹配。这有什么意义呢?这是否意味着我应该始终将函数指针传递给 return int 的函数?或者这只是(故意的?)生成错误?
gfortran 正在按设计和记录工作(在第二段的问题中实际引用了相关文档!)这里。
子例程测试采用通用 C 函数指针作为参数。从该子程序接口的互操作性的角度来看,可以传入任何函数。gfortran 对任何函数的匹配函数的解释是“指向返回 int 的函数的指针,没有显式参数列表”。
Fortran 过程指针与函数指针的关联是一个执行时间activity。原型描述了函数的特性,是一个编译时的概念。
gfortran 编译器具有 interoperability option -fc-prototypes,它为可互操作的函数(具有 BIND(C) 属性)生成正确的 C 原型。
在 link 中写道:“对于函数指针,生成一个指向函数 returning int 且没有显式参数列表的指针。”
我尝试了一些包含 BIND(C) 子例程的代码,该子例程采用指向具有 2 个整数参数的子例程的函数指针。取文件 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
编译为: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)()
这根本不匹配。这有什么意义呢?这是否意味着我应该始终将函数指针传递给 return int 的函数?或者这只是(故意的?)生成错误?
gfortran 正在按设计和记录工作(在第二段的问题中实际引用了相关文档!)这里。
子例程测试采用通用 C 函数指针作为参数。从该子程序接口的互操作性的角度来看,可以传入任何函数。gfortran 对任何函数的匹配函数的解释是“指向返回 int 的函数的指针,没有显式参数列表”。
Fortran 过程指针与函数指针的关联是一个执行时间activity。原型描述了函数的特性,是一个编译时的概念。