我没有使用Fortran的经验,但我试图通过.Fortran()函数从R调用它来运行该语言的一个非常简单的循环。每当我运行下面粘贴的R代码的最后一行时,R gui崩溃,我得不到任何结果。我有兴趣将Fortran的实数x向量带回R进行进一步分析。 g是0到1之间的数值,n是整数,它们都由用户在R中提供。
任何帮助将不胜感激!最好的,
文森特
Fortran代码保存在bar.f中:
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
使用gfortran在Cygwin中编译DLL:
gfortran -shared -obar.dll bar.f
R代码:
dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))
答案 0 :(得分:25)
编译代码时,我可以执行一次.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)
函数发送空向量,其中{{1} }是要生成的空向量的长度:
n
.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))
和integer
是返回character
等向量的有用函数。
自从你提到你以来,关于Fortran风格的一些友好建议也刚刚开始使用该语言:
使用double
扩展名命名文件可能是明智的 - 大多数编制者都假定以.f90
结尾的文件遵循旧的“固定格式”格式是PITA,因为它被设计用于打卡。
.f
... Do 100
语句是Fortran 77中的结尾循环样式。现代等价物是100 continue
.. Do
。
使用Fortran函数和子例程,声明传入和传出例程的变量的“意图”是明智的。可用的意图声明是:
end do
:表示仅作为输入进入例程的变量。进入例程后,它们应被视为参数,如果尝试更改它们,编译器将引发错误。
intent(in)
:表示应在例程中生成值的变量作为输出。如果未在例程中分配intent out变量,编译器将发出警告。
intent(out)
:表示可能进入带有一组特定值的例程的变量,并使例程保持不同的值。
设置变量意图将有助于编译器生成警告和错误,可以帮助您节省一些错误。
Fortran有一个默认行为,如果其名称以i-n开头,则例程头中未声明的任何变量都是整数,否则为real。这可能会导致拼写错误的变量名称“神奇地”成为变量,而编译器不会引起注意或告诉您。在例程顶部设置intent(inout)
会禁用此行为,并允许编译器通知您可能非常难以追踪的错误。
考虑这些建议的子程序版本如下所示:
implicit none
此外,让R使用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
的{{1}}子命令编译库是很有用的:
SHLIB
这将针对包含有用功能的R库编译程序,例如BLAS例程,统计例程和可以将信息打印到R控制台的方法。有关详细信息,请参阅Writing R Extensions, Section 6。
希望这有帮助!