R&Fortran电话

Vin*_*ent 12 fortran r

我没有使用Fortran的经验,但是我试图通过使用.Fortran()函数从R调用它来运行该语言中的一个非常简单的循环.每当我运行下面粘贴的R代码的最后一行时,R gui崩溃,我得不到任何结果.我有兴趣将Fortran的实数x向量带回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
Run Code Online (Sandbox Code Playgroud)

使用gfortran在Cygwin中编译DLL:

gfortran -shared -obar.dll bar.f
Run Code Online (Sandbox Code Playgroud)

R代码:

dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))
Run Code Online (Sandbox Code Playgroud)

Sha*_*pie 26

当我编译你的代码时,我可以执行.Fortran一次调用.当我第二次运行时,它会崩溃.但是,我注意到如果我传递的矢量x长度与传递的整数相同,则n表明它应该是,即:

.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )
Run Code Online (Sandbox Code Playgroud)

我可以根据需要多次运行该功能.所以问题可能是你告诉Fortran例程它有一个长度为15的向量,但只发送一个长度为5的向量.这可能导致Fortran例程访问它本不应该的内存会解释一下崩溃.

因为看起来你正在生成x例程中的所有值,所以你可以跳过生成随机数,然后使用R double(n)函数发送一个空向量,其中n是你想要生成的空向量的长度:

.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))
Run Code Online (Sandbox Code Playgroud)

integer并且character是返回向量之类的有用函数double.

关于Fortran风格的一些友好建议,因为你提到你只是开始使用该语言:

  • .f90扩展名命名文件可能是明智的--- .f大多数编译器都假定文件结尾,以遵循旧的"固定格式"格式,这是一种PITA,因为它设计用于打卡.

  • Do 100... 100 continue语句是Fortran 77中结束循环的风格相当于现代的是Do... end do.

  • 使用Fortran函数和子例程,声明传入和传出例程的变量的"意图"是明智的.可用的意图声明是:

    • intent(in):表示仅作为输入进入例程的变量.进入例程后,应将它们视为参数,如果尝试更改它们,编译器将引发错误.

    • intent(out):表示应在例程内生成值作为输出的变量.如果未在例程中分配intent out变量,编译器将发出警告.

    • intent(inout):表示可能进入带有一组特定值的例程的变量,并使例程保持不同的值.

    在变量上设置意图将有助于编译器生成警告和错误,这可能会为您节省一些错误.

  • Fortran有一个默认行为,其中任何未在例程头中声明的变量如果名称以in开头则为整数,否则为real.这可能会导致拼写错误的变量名称"神奇地"成为变量而无需编译器瞄准或告诉您.设置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
Run Code Online (Sandbox Code Playgroud)

另外,让R使用以下SHLIB子命令编译库是很有用的R CMD:

R CMD SHLIB -o bar.dll bar.f90
Run Code Online (Sandbox Code Playgroud)

这将针对包含有用函数的R库编译程序,例如BLAS例程,统计例程和可以将信息打印到R控制台的方法.有关详细信息,请参阅编写R扩展,第6节.

希望这可以帮助!

  • 非常好的答案.但是也要查看内联包,因为它有助于编译,链接和加载步骤. (3认同)