我正在编写一些R模拟代码,但希望利用Fortran的swift线性代数库来替换核心迭代循环。到目前为止,我主要关注使用.Fortran调用链接的F95子例程的明显选项;我想我应该优化内存使用(我传递非常大的数组)并设置DUP=FALSE
但是我在手册中读到了关于这种方法的危险性以及它在R 3.1.0中的折旧和R 3.2中的禁用的警告0.0。现在手册建议切换到.Call
,但此功能本身不提供Fortran支持。
我的谷歌搜索已经产生了a stackoverflow question,它探索了一种将Fortran子程序通过C代码与使用.Call
调用它的方法。在我看来,这种事情可能像魅力或诅咒一样起作用。因此,我的问题是:
.Fortran
和.Call
致电Fortran有哪些风险和好处?.Call
调用Fortran子例程是否有更优雅/更有效的方式?答案 0 :(得分:2)
以下是我对这种情况的看法:
.Call
是通常首选的界面。它直接为您提供了指向底层R数据对象(SEXP
)的指针,因此您决定进行所有内存管理。如果需要,您可以尊重NAMED
字段并复制数据,或忽略它(如果您知道您不会修改数据,或者由于其他原因而感到很舒服)
.Fortran
尝试从R SEXP
对象自动提供适当的数据类型到Fortran子例程;但是,它的使用通常是不鼓励的(原因并不完全清楚,说实话)
您应该从C / C ++例程中调用编译的Fortran代码。给定名为fortran_subroutine
的Fortran子例程,您应该能够在C / C ++代码中提供前向声明,例如: (注意:你需要一个领先的extern "C"
C ++代码):
void fortran_subroutine_(<args>);
请注意函数名称的尾随下划线 - 这是Fortran编译器(我熟悉的,例如gfortran
)默认情况下“破坏”符号名称的方式,因此可用的符号将具有尾随下划线。
此外,您需要确保选择的<args>
映射到相应的C类型到相应的Fortran类型。幸运的是,R-exts提供了这样一个表格。
最后,R R CMD build
会自动促进R包的编译+链接过程。因为我显然是一个贪婪的惩罚,我produced an example package应该提供足够的信息让你了解绑定在那里是如何工作的。
答案 1 :(得分:2)
3。共有其他选择吗?是
R包 dotCall64 可能是一个有趣的选择。它提供.C64()
,它是外国功能接口的增强版本,即.C()
和.Fortran()
。
接口.C64()
可用于接口Fortran和C / C ++代码。它
.C()
和.Fortran()
的用法类似因此,可以避免不必要的只读参数副本,同时避免将.Call()
接口与C包装函数结合使用。
一些链接:
我是 dotCall64 和垃圾邮件的作者之一。