我正在编写一些R模拟代码,但希望利用Fortran的swift线性代数库来替换核心迭代循环。到目前为止,我主要关注使用.Fortran调用链接的F95子例程的明显选项;我想我应该优化内存使用(我传递的是非常大的数组)并设置DUP=FALSE
,但后来我在手册中读到了关于这种方法的危险性及其在R 3.1.0中的折旧和R 3.2.0中的禁用的警告。现在手册建议切换到.Call
,但此功能本身不提供Fortran支持。
我的谷歌搜索产生了a stackoverflow question,探索了一种通过C代码链接Fortran子程序和使用.Call
调用它的方法。在我看来,这种事情可能像魅力或诅咒一样起作用。因此,我的问题:
.Fortran
和.Call
调用Fortran的风险和好处是什么?.Call
来调用Fortran子程序?以下是我对这种情况的看法:
.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
)默认情况下的'mangle'符号名称,因此可用的符号将具有该尾随下划线。
此外,您需要确保选择的<args>
映射到相应的C类型到相应的Fortran类型。幸运的是,R-exts提供了这样一张桌子。
最后,R的R CMD build
将自动促进R包的编译+链接过程。因为我显然是一个贪婪的惩罚,我有produced an example package应该提供足够的信息,让你了解绑定如何在那里工作。
3.还有其他选择吗?是
R包dotCall64可能是一个有趣的选择。它提供.C64()
,它是外部函数接口的增强版本,即.C()
和.Fortran()
。
接口.C64()
可用于连接Fortran和C / C ++代码。它
.C()
和.Fortran()
的用法因此,可以避免不必要的只读参数副本,同时避免将.Call()
接口与C包装函数结合使用。
一些链接:
我是dotCall64和垃圾邮件的作者之一。