当我编译你的代码时,我可以执行一次对.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 .. end do。
-
对于 Fortran 函数和子例程,明智的做法是声明传入和传出例程的变量的“意图”。可用的意图声明是:
intent(in):表示仅作为输入进入例程的变量。一旦进入例程,它们应被视为参数,如果尝试更改它们,编译器将引发错误。
intent(out):表示其值应在例程中生成的变量作为输出。如果在例程中未分配意图输出变量,编译器将发出警告。
intent(inout):表示可以携带一组值进入例程并以不同值离开例程的变量。
在变量上设置意图将有助于编译器生成警告和错误,这可能会为您节省一些寻找错误的时间。
Fortran 有一个默认行为,其中未在例程头中声明的任何变量如果其名称以 i-n 开头,则为整数,否则为实数。这可能会导致拼写错误的变量名称“神奇地”成为变量,而编译器不会注意到或告诉您。在您的例程顶部设置 implicit none 会禁用此行为,并允许编译器通知您可能很难追踪的错误。
将这些建议考虑在内的子例程版本如下所示:
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 使用 R CMD 的 SHLIB 子命令编译您的库很有用:
R CMD SHLIB -o bar.dll bar.f90
这将针对包含有用功能的 R 库编译您的程序——例如 BLAS 例程、统计例程和可以将信息打印到 R 控制台的方法。请参阅Writing R Extensions, Section 6 了解更多信息。
希望这会有所帮助!