This post is a version of the rcpp-and-fortran README from the R&D Rcpp collection of compiled-code examples. The repository holds the full, runnable source.
This small example R package demonstrates how to call a Fortran routine from C++ code that is exposed to R with Rcpp, using Fortran’s iso_c_binding module to give the routine C linkage so the two languages can interoperate. It is one of the R&D Rcpp prototype packages, a collection of minimal examples for integrating compiled code with R.
The fRcpp R package provides an example of calling a Fortran routine from C++ code that is, in turn, exposed to R with Rcpp. The Fortran routine is given C linkage through the iso_c_binding module so the C++ side can call it directly.
Usage
To install the package, you must first have a compiler on your system that is compatible with R, including a Fortran compiler such as gfortran. For help on obtaining a compiler consult either macOS or Windows guides.
With a compiler in hand, one can then install the package from GitHub by:
# install.packages("remotes")
remotes::install_github("coatless-rd-rcpp/rcpp-and-fortran")
library("fRcpp")Implementation Details
Within this project, a numerical routine is written in Fortran and called from an Rcpp function. The bridge between the two languages is Fortran’s iso_c_binding module, which gives the routine C linkage: a predictable symbol name and argument types that C++ can match. The example routine sums the elements of a numeric vector.
.
├── DESCRIPTION # Package metadata
├── NAMESPACE # Function and dependency registration
├── R # R functions
│ ├── RcppExports.R # Autogenerated R to C++ bindings by Rcpp
│ └── fRcpp-package.R # Package documentation
├── README.md
├── man # Package documentation
│ ├── fRcpp-package.Rd
│ └── fortran_sum.Rd
├── rcpp-and-fortran.Rproj
└── src # Compiled code
├── Makevars # Links the Fortran runtime via FLIBS
├── Makevars.win
├── RcppExports.cpp # Autogenerated R bindings
├── fsum.f90 # The Fortran routine (bind(C))
└── surface_fortran.cpp # Rcpp wrapper that calls the Fortran routineThe Fortran Routine
The routine lives in src/fsum.f90. The bind(C, name = "fsum") attribute fixes its symbol name to fsum and, together with the iso_c_binding kinds (c_double, c_int), pins its argument types. The length n is passed by value, while the array x and the result total are passed by reference, matching how C would pass them.
subroutine fsum(x, n, total) bind(C, name = "fsum")
use, intrinsic :: iso_c_binding, only : c_double, c_int
implicit none
integer(c_int), intent(in), value :: n
real(c_double), intent(in) :: x(n)
real(c_double), intent(out) :: total
integer :: i
total = 0.0_c_double
do i = 1, n
total = total + x(i)
end do
end subroutine fsumCalling Fortran from Rcpp
The wrapper in src/surface_fortran.cpp declares the routine inside an extern "C" block so the C++ compiler resolves it with C linkage and the unmangled name fsum. The exported fortran_sum() function then hands the vector’s underlying buffer and length to the routine and returns the computed sum.
#include <Rcpp.h>
// Declare the Fortran routine with C linkage.
extern "C" {
void fsum(const double* x, int n, double* total);
}
// [[Rcpp::export]]
double fortran_sum(Rcpp::NumericVector x) {
int n = x.size();
double total = 0.0;
fsum(x.begin(), n, &total);
return total;
}The exported function also carries //' roxygen comments (trimmed from the excerpt here) that Rcpp::compileAttributes() copies into R/RcppExports.R to generate the help page. From R the routine is called as:
fortran_sum(1:10)
#> [1] 55Linking the Fortran Runtime
Because the package mixes C++ and Fortran, the Fortran runtime libraries must be linked into the shared object. src/Makevars and src/Makevars.win request them with R’s $(FLIBS) variable.
PKG_LIBS = $(FLIBS)DESCRIPTION
Surfacing the C++ code with Rcpp requires Rcpp under both LinkingTo (for the headers used at compile time) and Imports (so it is available at run time).
LinkingTo:
Rcpp
Imports:
Rcpp (>= 1.0.12)Source
The full package source is available on GitHub, and the rendered package site can be found at rd-rcpp.thecoatlessprofessor.com/rcpp-and-fortran.