Awesome
<!-- README.md is generated from README.Rmd. Please edit that file -->simplefortran - demo package for calling C code with .C()
<!-- badges: start -->
<!-- badges: end -->
simplefortran
is a small demo package showing how Fortran code could
be included in a package and called with .Fortran()
This is one of a series of small demo packages for
calling other languages from R:
- {simplec} - calling C
with
.C()
- {simplecall} -
calling C with
.Call()
- {simplercpp} -
calling C++ with
{Rcpp}
- {simplefortran} -
calling Fortran with
.Fortran()
Rough comparison of .C()
, .Call()
, {Rcpp}
(and .Fortran()
)
.C() | .Call() | Rcpp | |
---|---|---|---|
Overview | No real understanding of R objects | Need to understand SEXP macros & internals | C++ classes hide the complexity of the SEXP internals |
What code? | Basic C code. Numeric calcs. | Complex C code. Can manipulate R objects from C | Complex C and C++ code involving numerics and R objects |
Pros | Simple to understand and use | Simple. No unnecessary copying. | Great documentation. Wrapping of R objects very intuitive. |
Cons | Too simple for most interesting things | Need to understand SEXP & R internals | |
Cons | Performs copying of data to call functions | ||
Demo R package | {simplec} | {simplecall} | {simplercpp} |
Compiled size | 17 kB | 17 kB | 92 kB (stripping can bring this down: see issue1) |
.Fortran() | |
---|---|
Overview | No real understanding of R objects |
What code? | Basic Fortran code. Numeric calcs. |
Pros | Simple to understand and use |
Cons | Too simple for most interesting things |
Cons | Performs copying of data to call functions |
Cons | Need to know Fortran! |
Demo R package | {simplefortran} |
Compiled size | 17 kB |
Installation
You can install from GitHub with:
# install.package('remotes')
remotes::install_github('coolbutuseless/simplefortran)
What’s in the box?
Package contains 2 Fortran functions, and 2 functions in R which call
the Fortran functions using .Fortran()
.
Fortran function | R function |
---|---|
subroutine add_(x, y, answer) | add_Fortran(x, y) |
subroutine mul_(x, y, answer) | mul_Fortran(x, y) |
What’s in the R functions?
- A call using
.Fortran()
- First argument is the Fortran function name e.g.
add_
x
andy
arguments are passed through from the R function- the third argument to the function is space in which to store the
result i.e.
numeric(1)
.Fortran()
returns as many arguments as you gave it originally- We only want to return the actual result, which is the third
argument, hence
[[3]]
@useDynLib [packagename] [Fortran function name]
is used to generate the NAMESPACE entryuseDynLib(simplefortran, add_)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Add two numbers
#'
#' @param x,y numbers to add
#'
#' @useDynLib simplefortran add_
#' @export
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
add_Fortran <- function(x, y) {
.Fortran(add_, x, y, numeric(1))[[3]]
}
What’s in the Fortran functions?
- Actual result must be stored in one of the arguments
subroutine add_(x, y, answer)
c
c add 2 numbers
c
double precision x, y, answer
answer = x + y
end
How do R variables map to Fortran variables?
- See R manual on writing Extensions for more info
R | Fortran |
---|---|
logical | INTEGER |
integer | INTEGER |
double | DOUBLE PRECISION |
complex | DOUBLE COMPLEX |
character | CHARACTER(255) |
raw | (none) |
What does the Fortran function look like in R?
- An object of class
NativeSymbolInfo
- Holds an
externalptr
to the loaded function
simplefortran:::add_
#> $name
#> [1] "add_"
#>
#> $address
#> <pointer: 0x1055e3ec0>
#> attr(,"class")
#> [1] "NativeSymbol"
#>
#> $dll
#> NULL
#>
#> attr(,"class")
#> [1] "NativeSymbolInfo"
Resources
- Peter Dalgaard’s Keynote from UseR 2004 discusses R’s language interfaces
- Using R — Calling C Code ‘Hello World’
- Hadley’s Advanced R book chapter - ‘Rs C interface’
- Rcpp
Acknowledgements
- R Core for developing and maintaining such a wonderful language.
- CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining the repository