我没有使用 Fortran 的经验,但我试图通过 .Fortran() 函数从 R 中调用该语言来运行一个非常简单的循环。每当我运行粘贴在下面的 R 代码的最后一行时,R gui 就会崩溃并且我没有得到任何结果。我有兴趣将实值 x 的向量从 Fortran 带回 R 以进行进一步分析。 g 是 0 到 1 之间的数值,n 是整数,它们都由用户在 R 中提供。
任何帮助将非常感激!最好,
文森特
保存在 bar.f 中的 Fortran 代码:
subroutine bar(n, g, x)
integer n
double precision g
double precision x(n)
integer i
x(1)=1
do 100 i = 2, n
x(i) = x(i-1) * g + 1
100 continue
end
在 Cygwin 中使用 gfortran 编译 DLL:
gfortran -shared -obar.dll bar.f
代码:
dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))
最佳答案
当我编译你的代码时,我可以执行一次对 .Fortran
的调用。当我第二次运行它时,它崩溃了。但是,我注意到,如果我使为 x
传递的向量与为 n
传递的整数长度相同,则表明它应该是,即:
.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )
我可以根据需要多次运行该函数。所以问题可能是你告诉 Fortran 例程它有一个长度为 15 的向量可以使用,但只发送一个长度为 5 的向量。这可能导致 Fortran 例程访问它不应该访问的内存会解释崩溃。
由于看起来您正在例程中生成
x
的所有值,因此您可以跳过生成随机数并使用 R 的 double(n)
函数发送一个空向量,其中 n
是您想要生成的空向量的长度:.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))
integer
和 character
是有用的函数,它们返回像 double
这样的向量。还有一些关于 Fortran 风格的友好建议,因为您提到您刚刚开始使用该语言:
.f90
扩展名来命名您的文件可能是明智的——大多数编译器都假设以 .f
结尾的文件遵循旧的“固定格式”格式,该格式是设计用于 PITA 的卡片. Do 100
... 100 continue
语句是 Fortran 77 中结束循环的一种风格。现代的等价物是 Do
x322513 .18 end do
:表示仅作为输入进入例程的变量。一旦进入例程,它们就应该被视为参数,如果尝试更改它们,编译器将引发错误。 intent(in)
:表示其值应在例程内作为输出生成的变量。如果在例程中未分配意图输出变量,编译器将发出警告。 intent(out)
:表示可以携带一组特定值进入例程并以不同值离开例程的变量。 在变量上设置意图将帮助编译器生成警告和错误,这可能会为您节省一些错误搜索。
intent(inout)
会禁用此行为,并允许编译器通知您可能很难追踪的错误。 考虑到这些建议的子程序版本如下所示:
subroutine bar(n, g, x)
implicit none
integer, intent(in):: n
double precision, intent(in):: g
double precision, intent(inout):: x(n)
integer:: i
x(1) = 1
do i = 2, n
x(i) = x(i - 1) * g + 1
end do
end subroutine bar
此外,让 R 使用
implicit none
的 SHLIB
子命令编译您的库很有用:R CMD SHLIB -o bar.dll bar.f90
这将针对包含有用函数的 R 库编译您的程序——例如 BLAS 例程、统计例程和可以将信息打印到 R 控制台的方法。有关更多信息,请参阅 Writing R Extensions, Section 6。
希望这可以帮助!
关于R & Fortran 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4731807/