为可选的 fortran 参数传递一个值,该参数将 return false for present()
Passing a value for an optional fortran parameter that will return false for present()
我想找到一种方法让 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
有什么方法可以根据 scalarC
的存在设置 scalar
变量,使其在 scalarC
不存在时看起来不存在?
一些约束:
我宁愿避免涉及对 optionaltest
的不同调用的 if 语句,因为子例程的真实版本有几个可选参数,可以单独指定或不指定,导致组合爆炸。
我不能将 optionaltest
子例程直接绑定为 C 函数,因为子例程的真实版本已经假定形状可选参数,这在 Fortran 版本中与 C 不兼容我正在使用
我无法修改optionaltest
的签名。
子程序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,所以这种方法可能行不通。在这种情况下,我会让其他人以特定方式回答,但这可能仍然值得记录,以便 others/after 升级。
1如果c_double
有值8
,这个问题可能不是这种情况,但我们还是会考虑。
我想找到一种方法让 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
有什么方法可以根据 scalarC
的存在设置 scalar
变量,使其在 scalarC
不存在时看起来不存在?
一些约束:
我宁愿避免涉及对
optionaltest
的不同调用的 if 语句,因为子例程的真实版本有几个可选参数,可以单独指定或不指定,导致组合爆炸。我不能将
optionaltest
子例程直接绑定为 C 函数,因为子例程的真实版本已经假定形状可选参数,这在 Fortran 版本中与 C 不兼容我正在使用我无法修改
optionaltest
的签名。
子程序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,所以这种方法可能行不通。在这种情况下,我会让其他人以特定方式回答,但这可能仍然值得记录,以便 others/after 升级。
1如果c_double
有值8
,这个问题可能不是这种情况,但我们还是会考虑。