【问题标题】:Different number parameters calling C routine from FORTRAN 90从 FORTRAN 90 调用 C 例程的不同数字参数
【发布时间】:2013-07-16 06:07:08
【问题描述】:

我正在从 FORTRAN 90 代码中调用 C 例程。一切正常,但我想知道为什么以及如何使用更少的参数调用 C 例程,我应该编译器不会抱怨。编译器在这里做什么?我正在使用 Cray 编译器。

test.c

extern "C" void test_(double* x, double* y, double* z){
    // do some work
}

driver.F90

MODULE DRIVER

! declare arrays
 DOUBLE PRECISION, DIMENSION(dim, dim), INTENT(IN) :: x
 DOUBLE PRECISION, DIMENSION(dim, dim), INTENT(IN) :: y

! call C subroutine
 CALL test(x, y)

END MODULE DRIVER

【问题讨论】:

  • 可能测试函数弹出一个未定义的值,您的 fortran 没有推送到堆栈(或推送可能为零的 null)。示例: push x,y,z pop z,y,x 但没有做最新的 push 所以是 push x,y pop z(it was y),y(it was x),undefined x(no push/null)
  • 在你的 C 方法中打印 z 并找出答案。在调用外部方法时,您应该始终确保传入正确的数字参数,因为每个编译器都不同。它要么将 z 设置为默认值(零或空),要么会破坏堆栈,并且您将遇到一些内存问题,这些问题可能会进一步显示...
  • 我不敢相信这被否决了。
  • 编译器不会“抱怨”,因为 Fortran 编译器不知道您错误地调用了 C 例程。您很容易遇到运行时错误(崩溃)。如果您使用 Fortran ISO_C_Binding 并使用 Fortran 接口正确描述了 C 例程,Fortran 编译器将检测到不正确的调用并在编译时发出错误消息。

标签: c fortran cray


【解决方案1】:

在函数调用方面,Fortran 与 C 有很大不同。将参数传递给 C 例程时,编译器必须知道每个参数的类型,以便它可以生成适当的调用序列 - 将参数以正确的顺序和正确的填充放在堆栈上,或者将它们放在预期的寄存器。如果调用者在调用者之前定义,C 编译器通常会在编译代码时收集此信息。在所有其他情况下,应提供原型形式的函数声明。

在 Fortran 中,所有参数通常(有一些例外)通过地址传递,这意味着实际传递给被调用者的是一组内存指针。指针看起来是一样的——它们总是属于同一类型,因此以相同的方式传递。因此,Fortran 编译器可以在不知道被调用者实际期望什么参数的情况下生成函数调用。这极大地简化了 Fortran 编译器,但却是无数可能错误的来源,例如使用错误的参数类型甚至错误数量的参数调用函数,仅举几例。通常必须使用称为 linter 的特殊程序(来自 C 程序验证实用程序 lint 的名称),以确保不存在此类错误。现代 Fortran 编译器也试图比旧的编译器更严格,并尽可能地检测错误。

现代 Fortran 版本提供 INTERFACE 构造,允许显式声明函数接口,这与 C 中的函数原型非常相似。模块子例程和函数自动生成它们的接口,并提供给 USE 模块的调用者.当调用具有显式接口的子例程/函数时,编译器能够验证调用的有效性,即它检查参数的数量及其类型是否与接口中的相匹配。

您应该为外部例程提供一个接口,然后编译器将能够执行检查。通常使用ISO_C_BINDING 方法来连接C 代码:

INTERFACE
  SUBROUTINE test(x, y, z) BIND(C, NAME="test")
    USE, INTRINSIC :: ISO_C_BINDING
    REAL(KIND=C_DOUBLE), INTENT(...) :: x  ! Put the proper intents
    REAL(KIND=C_DOUBLE), INTENT(...) :: y
    REAL(KIND=C_DOUBLE), INTENT(...) :: z
  END SUBROUTINE test
END INTERFACE

有了这个接口,CALL test(x, y) 会因为参数计数不匹配而导致编译时错误。

【讨论】:

  • @_Hristo 谢谢。我会试试的。学习新东西总是有益的。
猜你喜欢
  • 2010-10-24
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 2014-01-14
  • 2012-01-02
相关资源
最近更新 更多