【发布时间】:2020-10-22 18:30:03
【问题描述】:
gfortran 编译器具有interoperability option -fc-prototypes,它为可互操作的函数(具有 BIND(C) 属性)生成正确的 C 原型。
在链接中写道:“对于函数指针,会生成一个指向返回 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)()
这根本不匹配。这有什么意义?这是否意味着我应该始终将函数指针传递给返回 int 的函数?还是这只是(故意?)产生的错误?
【问题讨论】:
-
需要看一些实际代码。
-
@evets 我添加了一些代码。
-
虚拟参数
pf的类型是c_funptr:你为什么希望gfortran 生成void (*pf)(int, int)? -
@francescalus 因为在 C 端,我必须将指向
void (*)(int, int)类型的函数而不是int(*)()类型的函数的指针传递给test函数。生成错误的 C 接口有什么意义?还是 Fortran 代码不正确,我应该使用不同于c_funptr的东西?但是它编译时没有任何警告。 -
如果你没有那个
c_f_procptr调用,或者它被使用了两次不同的原型(有条件地,可能),或者它是一个隐式接口怎么办?也就是说,gfortran 不能涵盖所有情况,所以它必须选择一些东西。 (你现在有一个涵盖这个的答案,所以最好在那里继续进一步讨论。)
标签: c fortran function-pointers gfortran fortran-iso-c-binding