6

在 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

如果用户调用fs_WriteData_d('name', data)数据是双精度的,最多 4 维数组,这个子例程就可以完成这项工作。

现在,问题是:我想提供一个名为 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、... 子程序的内容相同,从而使模块更易于维护?

提前谢谢了。

4

1 回答 1

7

有点。

正如您所发现的,从 F2008 开始,为通用调用选择特定过程的规则除其他事项和基本过程外,还需要类型、种类和等级的匹配(所谓的 TKR 兼容)。即使假定数据虚拟参数的大小(因此在直接调用特定过程时,它可以与任何非零等级的实际参数相关联),出于 TKR 兼容性的目的,它仍被视为等级一的参数。

最近发布的关于 Fortran 与 C 的进一步互操作性的技术规范 (TS29113) 增加了假定等级的概念。根据您在可执行部分fs_WriteData_d(传递给 C 几乎是您可以做的所有事情)中所做的事情,可能适合 - 类型/种类/等级匹配的规则已经扩展,因此假定等级实际或虚拟参数是兼容的等级的。相当重要的问题是编译器支持——我认为目前没有任何编译器支持这个 TS!

对于 F201X 之前的语言标准编码,有几种可能性:

  • 为您想要支持的每个等级编写一系列瘦包装子例程,然后这些包装子例程调用一维形式的特定过程,依靠序列关联将多维数组映射到一维数组。

  • 将子程序的主体放在一个单独的文件中,并将该文件包含在每个等级的子程序的骨架接口中。这种方法要求子程序主体内的代码在词法上是独立的。在某些情况下,代码也可以以独立于类型的方式编写,您可以使用一个通用的包含文件来处理您想要支持的各种类型。虽然这消除了与“复制和粘贴”代码的更改管理相关的问题,但处理 INCLUDE 文件可能有点痛苦。

两者的某种组合也可能是合适的。

(可能存在第三种选择,使用 C 互操作性将为每个等级和类型组合编写的接口主体的绑定名称设置为一个实现过程的绑定名称,但我不确定 C 的(ab)用法是否互操作性是合法的。)

如果您所追求的只是不同类型变体的通用命名,那么另一种可能性(再次取决于您在正文中所做的事情)是将数据参数作为 ISO_C_BINDING 内在模块中的 C_PTR 并推动采取的要求将实际参数的 C_LOC 返回到子例程的客户端代码中。

于 2013-01-21T08:37:00.133 回答