为可选的fortran参数传递一个值,该参数将为present()返回false

时间:2017-04-11 16:21:37

标签: fortran optional-parameters

我想找到一种方法来获取一个fortran方法,为可选参数取一些值,使参数看起来不会出现在被调用的方法中。

这是一个简化的测试用例,用于提炼fortran代码中的问题:

MODULE FortranOptional
  USE ISO_C_BINDING

CONTAINS
  SUBROUTINE optionaltest(scalar)
    REAL(8), OPTIONAL, INTENT(IN) :: scalar

    IF (PRESENT(scalar)) THEN
      print *, "scalar is present: ", scalar
    ELSE
      print *, "scalar is NOT present"
    END IF

  END SUBROUTINE optionaltest

  SUBROUTINE optionaltest_c(scalarC) BIND(C, NAME="optionaltest_c")
    REAL(C_DOUBLE), OPTIONAL, INTENT(IN) :: scalarC
    REAL(8) :: scalar

    IF (PRESENT(scalarC)) THEN
      print *, "scalarC is present: ", scalarC
      scalar = scalarC
    ELSE
      print *, "scalarC is NOT present"
      ! Can I do something here to make scalar appear not present in optionaltest()?
    END IF

    CALL optionaltest(scalar)
  END SUBROUTINE optionaltest_c
END MODULE FortranOptional

以及相关的C ++测试代码:

extern "C"
{
void optionaltest_c(double*);
}

void testMethod()
{
    double v = 5.3;
    optionaltest_c(0);

    std::cout << "\n";

    optionaltest_c(&v);
}

产生:

scalarC is NOT present
scalar is present:    6.9118029901527309E-310

scalarC is present:    5.2999999999999998     
scalar is present:    5.2999999999999998     

有什么方法可以根据scalar的存在来设置scalarC变量,当scalarC不存在时,它会显示不存在?

一些限制:

  • 我更倾向于避免if语句涉及对optionaltest的不同调用,因为子例程的真实版本有几个可选参数,可以单独指定或不指定,导致组合爆炸。

  • 我无法将optionaltest子例程直接绑定为C函数,因为子例程的实际版本假定了形状可选参数,这在我正在使用的Fortran版本中不兼容C。

  • 我无法修改optionaltest

  • 的签名

1 个答案:

答案 0 :(得分:4)

在子例程optionaltest_c中,变量scalar是本地变量。如您所知,局部变量没有可选性的概念。

为了完整性,如果只是将可选的伪参数从optionaltest_c传递到optionaltest,那么

call optionaltest(scalarC)

就足够了。也就是说,可选的伪参数可以是过程的实际参数,其中相应的伪参数也是可选的,无论其是否存在。

所以,如果你需要做某种形式的操作,该怎么做? 1 我注意到你在伪参数和局部变量之间有内在的赋值。

在Fortran 2008下,有一个明智的选择:让局部变量可分配。如果未分配变量并且是可选的不可分配虚拟对象的实际参数,则将其视为不存在:

  subroutine optionaltest_c(scalarC) bind(C)
    type(type1), optional, intent(in) :: scalarC
    type(type2), allocatable :: scalar  ! Local, conformable with scalarC

    if (PRESENT(scalarC)) scalar=scalarC
    ...

    call optionaltest(scalar)
  end subroutine optionaltest_c

[您可能需要提供其他方法来分配scalar并设置其值,具体取决于您的编译器支持。]

scalarC存在时,scalar将被分配并具有其值。然后在调用时,存在伪参数。如果scalarC不存在,则scalar未分配,并且在调用时不存在伪参数。

这对于数组和标量也同样有用。

现在,我看到你提到gfortran 4.4.7,所以这种方法可行不行。在这种情况下,我会让其他人以特定方式回答,但这可能仍然值得记录,以便其他人/升级后获益。

1 如果c_double的值为8,则此问题可能不是这样,但无论如何我们都会考虑。