如何在使用可选参数的C++头文件中引用Fortran函数?我需要为每个可能的调用组合在头文件中提供原型吗?或者这是不可能的吗?
例如,Fortran:
subroutine foo(a, b, c) bind(c)
real, intent(in), optional :: a, b, c
...
end subroutine foo
如何在使用可选参数的C++头文件中引用Fortran函数?我需要为每个可能的调用组合在头文件中提供原型吗?或者这是不可能的吗?
例如,Fortran:
subroutine foo(a, b, c) bind(c)
real, intent(in), optional :: a, b, c
...
end subroutine foo
除非您将子程序 bind(C)
,否则至少在可移植性方面是不可能的。
一旦您将其设置为 bind(C)
,它只是传递一个指针,在C端可以为空。
subroutine foo(a, b, c) bind(C, name="foo")
use iso_c_binding, only: c_float
real(c_float), intent(in), optional :: a, b, c
...
end subroutine foo
(为了更好的可移植性,我在iso_c_binding
模块中使用了real(c_float)
,但这与本问题有些不相关)
在 C(++)中
extern "C"{
void foo(float *a, float *b, float *c);
}
foo(&local_a, NULL, NULL);
然后您可以编写一个调用 foo
并使用C++风格可选参数的C++函数。
在技术规范ISO/IEC TS 29113:2012中,Fortran允许这种能力与C进一步互操作,并在随后并入了Fortran 2018。
optional
属性作为虚拟参数。foo
过程在F2008下不是C可互操作的(即使使用bind(C)
)。但是,在F2008下可以模仿这个想法:使用type(c_ptr)
参数创建一个C可互操作的过程,该过程包装所需的Fortran过程。这个互操作包装器可以使用C_ASSOCIATED
检查空指针以确定是否存在向前传递的参数 - 如果存在,则传递解引用后的参数。module mod
use, intrinsic :: iso_c_binding
contains
subroutine foo_centry(a) bind(c,name='foo')
type(c_ptr), value :: a
real(c_float), pointer :: a_pass
nullify(a_pass)
if (c_associated(a)) call c_f_pointer(a, a_pass)
call foo(a_pass)
end subroutine foo_centry
subroutine foo(a)
real(c_float), optional :: a
end subroutine foo
end module mod
module mod
use, intrinsic :: iso_c_binding
interface
subroutine foo_fentry(a) bind(c,name='foo')
import c_ptr
type(c_ptr), value :: a
end subroutine foo_fentry
end interface
contains
subroutine foo(a)
real(c_float), optional, target :: a
if (present(a)) then
call foo_fentry(c_loc(a))
else
call foo_fentry(c_null_ptr)
end if
end subroutine foo
end module mod
请注意,由于使用c_loc
可能会受到限制:对于某些情况,您可能希望使用副本或采取其他保护措施。
foo_c(int* val)
并支持可选参数,我首先会创建一个子程序foo_f(val) bind(c, name='foo_c')
,其中type(c_ptr), value, intent(in) :: val
。然后包装子程序是foo_f_wrap(val)
,其中integer, intent(in), target, optional :: val
,如果val
存在,则调用fun_f(c_loc(val))
,否则调用fun_f(c_null_ptr)
。我的理解正确吗? - Michael Schlottke-Lakemper