我正在尝试将并行MPI Fortran程序链接到使用MPI的并行C库。软件架构以Fortran为中心,所以我试图尽可能多地保留在Fortran端。
所以我需要将C例程传递给MPI通信器的句柄。它们的形式为
int CFunction(int *something, MPI_Comm *Ccomm)
MPI附带了将Fortran转换为C通信器句柄的接口:
MPI_Comm MPI_Comm_f2c(MPI_Fint comm)
但是,这些例程应该从C调用,所以现在我必须添加C包装函数,我可以将Fortran通信器传递给:
int CFunction_FMPI(int *something, MPI_Fint *Fcomm)
{ MPI_Comm Ccomm; int status;
Ccomm = MPI_Comm_f2c(*Fcomm); // Convert Fortran->C communicator
status = CFunction(*something,*Ccomm); // Call original function
return status;
}
然后我不得不写第二个接口 - CFunction_FMPI
- 使用Fortran的C绑定来允许从Fortran调用它。
我的问题是:有没有更好的方法来做到这一点,即避免使用Fortran-> C通信器转换的C包装器?我想直接从Fortran调用MPI_Comm_f2c
并将结果存储在type(c_ptr)
或integer(c_int)
变量中是最好的,但由于没有简单/一般性,我无法做到这一点MPI_Comm
类型与Fortran之间的绑定。
答案 0 :(得分:2)
不,我不认为有更好的方法可以做到这一点。而且我会关注它并不是那么复杂。您可以查看我在
中使用的类似功能https://github.com/LadaF/PoisFFT/blob/master/src/f_mpi_comm_c2f.c
这与你的CFunction_FMPI
方向相反,只是翻译了传播者。它是从C到Fortran。
// This function is callable from Fortran. MPI_Comm_c2f itself may be just a macro.
MPI_Fint f_MPI_Comm_c2f(MPI_Comm *comm) {
return MPI_Comm_c2f(*comm);
}
它是从Fortran调用的
interface
integer function MPI_Comm_c2f(c_handle) bind(C, name="f_MPI_Comm_c2f")
use iso_c_binding
type(c_ptr), value :: c_handle
end function
end interface
重要的一点是,MPI_Comm_c2f
在某些MPI库中是一个C宏,而不是一个函数,所以你不能真正从Fortran中调用它。我很确定MPI_Comm_f2c
也可以是一个宏,因此你不能从Fortran中调用它。
你可以做的是创建一个Fortran函数,它只调用MPI_Comm_f2c
的C包装器,然后使用bind(C)
接口调用Fortran中的C函数
status = CFunction(something, c_comm)
因此避免为每个C函数创建一个包装器。你只需要一个Fortran接口块。
问题是你在Fortran *中没有MPI_Comm
(实际上它是指针或int)所以你必须使用不透明的指针。
MPI_Comm* f_MPI_Comm_f2c(MPI_Fint Fcomm)
{ MPI_Comm* Ccomm;
Ccomm = malloc(sizeof(MPI_Comm));
*Ccomm = MPI_Comm_f2c(Fcomm);
return Ccomm;
}
返回不透明指针type(c_ptr)
。 (检查潜在的C编码错误我甚至忘了使用分号。)
你不仅仅是将Fortran通信器转换为指向C通信器的指针。
type(c_ptr) :: c_comm
c_comm = f_MPI_Comm_f2c(comm)
* MPI-3中有一个派生类型type(MPI_Comm)
,但它包含一个必须由转换例程转换的整数组件。