simplefortran - demo package for calling C code with .C()
July 4, 2020 · View on GitHub
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_ xandyarguments 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
externalptrto 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