我正在尝试在两个Fortran子例程之间插入C++层.我还需要传递一个我不想在C++中声明的派生类型作为参数,因为我不需要访问它的数据,并且它在我的原始程序中是一个复杂的类型,反过来使用了很多其他类型.
我做了一个简单的Fortran程序:
module my_module
implicit none
type :: my_type
real :: x
end type my_type
end module my_module
subroutine fortran_subroutine(b)
use my_module
implicit none
type(my_type), pointer, intent(in) :: b
print *, b%x
end subroutine fortran_subroutine
program test
use my_module
implicit none
abstract interface
subroutine sub (b)
import :: my_type
type(my_type), pointer, intent(in) :: b
end subroutine sub
end interface
type(my_type), pointer :: a
procedure (sub), pointer :: f_ptr => null ()
procedure (sub) :: fortran_subroutine
allocate(a)
a%x = 1.0
f_ptr => fortran_subroutine
call c_plus_plus_layer(f_ptr,a)
end program
Run Code Online (Sandbox Code Playgroud)
这是C++中间层:
extern "C"
{
void c_plus_plus_layer_(void (*pointer_to_fortran_function)(void **), void ** x);
}
// Intermediate layer of C++ designed to launch a Fortran subroutine
void c_plus_plus_layer_(void (*pointer_to_fortran_function)(void **), void ** x)
{
pointer_to_fortran_function(x);
}
Run Code Online (Sandbox Code Playgroud)
但是,print在使用英特尔编译器(v13)编译时到达指令时出错,因为我丢失了存储在C++层某处的派生类型中的数据.
gcc和gfortran编译器不会返回任何内容.
我可以请你帮忙吗?
Fortran 2003有一种与C接口的新方法.模块iso_c_binding声明了一个type(c_ptr)表示的派生类型,void*以及value允许您按值传递指针的属性.它还包含过程c_loc()以及c_f_pointer()Fortran和C指针的转换.
对于过程指针,类似地type(c_funptr),过程c_funloc()和c_f_procptr()可用.
在标签fortran-iso-c-binding中研究了很多问题和答案
此外,通过使用该bind(C)属性,您可以extern(C)在C++中获得类似的效果,并且您不必担心名称损坏和尾随_.该bind(C)属性对于实现CFortran过程的真实行为很重要,例如value属性.
请注意,如果您使用bind(C)编译器,通常会警告您甚至引发错误,即Fortran pointer属性不能在此类过程中使用,因为C不会理解它.