I am writing some R simulation code, but want to leverage Fortran's swift Linear Algebra libraries to replace the core iteration loops. So far I was looking primarily at the obvious option of using .Fortran to call linked F95 subroutines; I figured I should optimize memory use (I am passing very large arrays) and set DUP=FALSE
but then I read the warning in manual about the dangers of this approach and of its depreciation in R 3.1.0 and disablement in R 3.2.0. Now the manual recommends switching to .Call
, but this function offers no Fortran support natively.
My googling has yielded a stackoverflow question which explores an approach of linking the Fortran subroutine through C code and the calling it using .Call
. This seems to me the kind of thing that could either work like a charm or a curse. Hence, my questions:
.Fortran
and via .Call
?.Call
to call Fortran subroutines?Here's my thoughts on the situation:
.Call
is the generally preferred interface. It provides you a pointer to the underlying R data object (a SEXP
) directly, and so all of the memory management is then your decision to make. You can respect the NAMED
field and duplicate the data if you want, or ignore it (if you know that you won't be modifying the data in place, or feel comfortable doing that for some other reason)
.Fortran
tries to automagically provide the appropriate data types from an R SEXP
object to a Fortran subroutine; however, its use is generally discouraged (for reasons not entirely clear to me, to be honest)
You should have some luck calling compiled Fortran code from C / C++ routines. Given a Fortran subroutine called fortran_subroutine
, you should be able to provide a forward declaration in your C / C++ code as e.g. (note: you'll need a leading extern "C"
for C++ code):
void fortran_subroutine_(<args>);
Note the trailing underscore on the function name -- this is just how Fortran compilers (that I am familiar with, e.g. gfortran
) 'mangle' symbol names by default, and so the symbol that's made available will have that trailing underscore.
In addition, you'll need to make sure the <args>
you choose map to from the corresponding C types to the corresponding Fortran types. Fortunately, R-exts provides such a table.
In the end, R's R CMD build
would automatically facilitate the compilation + linking process for an R package. Because I am evidently a glutton for punishment, I've produced an example package which should provide enough information for you to get a sense of how the bindings work there.
3. Is there another option altogether? YES
The R package dotCall64 could be an interesting alternative. It provides .C64()
which is an enhanced version of the Foreign Function Interface, i.e., .C()
and .Fortran()
.
The interface .C64()
can be used to interface both Fortran and C/C++ code. It
.C()
and .Fortran()
Hence, one can avoid unnecessary copies of read-only arguments while avoiding the .Call()
interface in combination with a C wrapper function.
Some links:
I am one of the authors of dotCall64 and spam.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With