在Fortran模块中,我有一个函数,它接受一个数组及其名称,从数据库(实际调用C函数)获取数组的形状,将数组复制到临时缓冲区并将缓冲区传递给另一个C处理它的功能。此Fortran函数的整数数据名称为fs_WriteData_i,实数为fs_WriteData_f,双精度为fs_WriteData_d。所有这些功能不仅接受一维阵列,还接受2D,3D和4D阵列,并且它们完美地工作。以下是其中一个子程序的接口:
subroutine fs_WriteData_d(fieldname, data)
use, intrinsic :: iso_c_binding
implicit none
real(c_double), dimension(*) :: data
character :: fieldname*(*)
! ...
end subroutine fs_WriteData_d
如果用户使用双精度数据(最多4维数组)调用fs_WriteData_d('name', data)
,则此子例程可以完成此任务。
现在,问题是:我想提供一个名为fs_WriteData的常见重载接口,所以我使用
interface fs_WriteData
module procedure fs_WriteData_i, &
fs_WriteData_f, &
fs_WriteData_d
end interface fs_WriteData
不幸的是,这不起作用:如果用户只调用fs_WriteData('name', data)
,编译器会声明找不到正确的实现,这是因为所有这些函数的排名不匹配。
有没有一种聪明的方法可以避免编写所有fs_WriteData_d_1d,fs_WriteData_d_2d,...子程序只有相同的内容,以使模块更易于维护?
非常感谢提前。
答案 0 :(得分:6)
排序。
正如您所发现的那样,除了F2008之外,选择通用调用的特定过程的规则除了其他方面和元素过程之外还需要类型,种类和等级的匹配(所谓的TKR兼容)。即使数据伪参数是假定大小(因此在直接调用特定过程时它可以与任何非零等级的实际参数相关联),它仍然被认为是TKR兼容性目的的一级参数。
最近发布的关于Fortran with C(TS29113)的进一步互操作性的技术规范增加了假设等级的概念。取决于你在fs_WriteData_d
的可执行部分内所做的事情(传递给C几乎就是你可以做的所有事情)可能适合 - 类型/种类/等级匹配的规则已被扩展,使得假设等级实际或无论秩如何,伪参数都是兼容的。相当重要的问题是编译器支持 - 我认为目前没有任何编译器支持这个TS!
对于F201X之前的语言标准编码,有几种可能性:
为每个要支持的排名编写一系列精简包装子程序,然后使用这些包装器子程序调用1D表单的特定过程,依靠序列关联将多维数组映射到1D数组
将子例程的主体放在一个单独的文件中,并将该文件包含在骨架接口内,以用于每个等级的子例程。这种方法要求子程序体内的代码在词法上是等级独立的。在某些情况下,代码也可以以独立于类型的方式编写,并且您可以为要支持的各种类型使用公共包含文件。虽然这消除了与“复制和粘贴”代码的更改管理相关的问题,但处理INCLUDE文件可能会有点痛苦。
两者的某些组合也可能是合适的。
(可能存在第三种选择,使用C互操作性为每个排名和类型组合设置的接口主体的绑定名称设置为一个实现过程的绑定名称,但我不确定是否(ab)使用C互操作性是合法的。)
如果您正在寻找不同类型变体的常见命名,那么另一种可能性(再次,取决于您在正文中所做的事情)是将数据参数作为C_PTR从ISO_C_BINDING内在模块中取出并推送要求将实际参数的C_LOC返回到子例程的客户端代码中。