Using Fortran Routines from Rcpp
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:
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] 55