如何从 R 调用 Fortran 程序
How to call a Fortran program from R
我完全不熟悉 Fortran 并且精通 R。
我收到了一个巨大的 Fortran 程序,其中包含大约 30 个子例程和大约 15 个函数以及许多其他代码行。
我被告知我需要从 R 调用 Fortran 程序。我一直在网上搜索方法
在 R 和 Fortran 之间建立这座桥梁,但收效甚微。
我可以从命令行成功执行 Fortran exe 文件并创建所需的输出。
Fortran 文件名为“FortFish.f”
一个问题:
在 R 中,我是调用 Fortran 程序还是必须分别调用 Fortran 函数和子例程?
在 R 中,我是否像这样调用整个 Fortran 程序?:R CMD SHLIB FortFish.f 然后使用:
dyn.load("FortFish.so")
如果我不能一次 运行 整个 Fortran 程序,我会根据要求 post 几个小的 Fortran 函数和子例程。
有没有人有 运行ning 使用 R 和 Fortran 的例子可以分享?
我的 Fortran 代码非常大,否则,我会 post 放在这里。
谢谢。
我看到三种可能性:
你单独编译Fortran程序,用R函数调用system()
。您必须以该程序可以读取的格式通过文件传递数据。
您使用 dyn.load()
编译从 R 加载的 DLL,然后使用 .Fortran()
调用 Fortran 函数。您可以轻松传递数值数据(标量、向量或数组),但字符串数据更难处理。数组被复制.
这种调用 DLL 函数的机制被认为过于简单,现在首选 .Call()
,但要使用 .Call()
,您必须编写 C 包装程序。
第二种可能我举个例子。
考虑 Fortran 中的一个子程序,该子程序通过 Horner 算法计算多项式:
subroutine horner(n, a, x, y)
implicit none
integer :: n, i
double precision :: a(n), x, y
y = a(n)
do i = n - 1, 1, -1
y = y * x + a(i)
end do
end subroutine
从命令行编译:
R CMD SHLIB horner.f90
从 R 调用它:
dyn.load("horner.dll")
horner <- function(a, x) {
.Fortran("horner", as.integer(length(a)), a, x, y=0)$y
}
horner(c(-2, 0, 1), 1.414)
如果您希望您的 Fortran 子例程将某些内容打印到 RStudio 控制台,您需要执行(至少在 Windows 上):
Sys.unsetenv("GFORTRAN_STDOUT_UNIT")
Sys.unsetenv("GFORTRAN_STDERR_UNIT")
这确实是一个微不足道的例子,更复杂的程序将需要更多的工作,但你明白了。
如果您的 Fortran 程序是独立的(它有一个 'program' 单元并且应该被编译为从命令行调用的可执行文件),并且如果您是 Fortran 的新手,我建议坚持有了第一个选择,会简单很多。这就是 seasonal packaged does: call the executable of Census' X13AS from within R. The executable is in the x13binary 包。
我完全不熟悉 Fortran 并且精通 R。 我收到了一个巨大的 Fortran 程序,其中包含大约 30 个子例程和大约 15 个函数以及许多其他代码行。 我被告知我需要从 R 调用 Fortran 程序。我一直在网上搜索方法 在 R 和 Fortran 之间建立这座桥梁,但收效甚微。 我可以从命令行成功执行 Fortran exe 文件并创建所需的输出。 Fortran 文件名为“FortFish.f”
一个问题:
在 R 中,我是调用 Fortran 程序还是必须分别调用 Fortran 函数和子例程?
在 R 中,我是否像这样调用整个 Fortran 程序?:R CMD SHLIB FortFish.f 然后使用: dyn.load("FortFish.so")
如果我不能一次 运行 整个 Fortran 程序,我会根据要求 post 几个小的 Fortran 函数和子例程。 有没有人有 运行ning 使用 R 和 Fortran 的例子可以分享?
我的 Fortran 代码非常大,否则,我会 post 放在这里。 谢谢。
我看到三种可能性:
你单独编译Fortran程序,用R函数调用
system()
。您必须以该程序可以读取的格式通过文件传递数据。您使用
dyn.load()
编译从 R 加载的 DLL,然后使用.Fortran()
调用 Fortran 函数。您可以轻松传递数值数据(标量、向量或数组),但字符串数据更难处理。数组被复制.这种调用 DLL 函数的机制被认为过于简单,现在首选
.Call()
,但要使用.Call()
,您必须编写 C 包装程序。
第二种可能我举个例子。 考虑 Fortran 中的一个子程序,该子程序通过 Horner 算法计算多项式:
subroutine horner(n, a, x, y)
implicit none
integer :: n, i
double precision :: a(n), x, y
y = a(n)
do i = n - 1, 1, -1
y = y * x + a(i)
end do
end subroutine
从命令行编译:
R CMD SHLIB horner.f90
从 R 调用它:
dyn.load("horner.dll")
horner <- function(a, x) {
.Fortran("horner", as.integer(length(a)), a, x, y=0)$y
}
horner(c(-2, 0, 1), 1.414)
如果您希望您的 Fortran 子例程将某些内容打印到 RStudio 控制台,您需要执行(至少在 Windows 上):
Sys.unsetenv("GFORTRAN_STDOUT_UNIT")
Sys.unsetenv("GFORTRAN_STDERR_UNIT")
这确实是一个微不足道的例子,更复杂的程序将需要更多的工作,但你明白了。
如果您的 Fortran 程序是独立的(它有一个 'program' 单元并且应该被编译为从命令行调用的可执行文件),并且如果您是 Fortran 的新手,我建议坚持有了第一个选择,会简单很多。这就是 seasonal packaged does: call the executable of Census' X13AS from within R. The executable is in the x13binary 包。