R Package Integration with Modern Reusable C++ Code Using Rcpp – Part 4
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Daniel Hanson is a full-time lecturer in the Computational Finance & Risk Management program within the Department of Applied Mathematics at the University of Washington.
In the previous post in this series, we looked at how to write interface files using Rcpp
to call functions and instantiate classes in standard and reusable C++, with a code interface and reusable code examples shown in the discussion. My original plan for this week was to show how to import that code into an RStudio Rcpp
project and build it into an R package, but as there are a number of steps in the setup and build process, we’ll first look at a very simple example to demonstrate these, and then we’ll turn our attention to importing the reusable C++ code next time.
The following discussion will be a step by step guide in the project configuration and build process with a single example .cpp
file that is included by default when creating an Rcpp
project in the RStudio IDE.
Creating an Rcpp Package Project in the RStudio IDE
Open the RStudio IDE, and select New Project...
from the File
menu at the top, and select New Directory
as shown here:
Next, you will see the following selections, from which you should choose R Package using Rcpp
. Be sure to make this selection, and not R package
alone as shown above:
Next, enter the desired directory path and new subdirectory name, and create the project; the subdirectory will be the name of your R package, e.g. RcppProject
:
When finished, your RStudio session should look something like this:
There is one more step to complete in order to ensure your interface functions will be exposed as R functions to your package users. In the Files
pane at lower right, you should see a file called NAMESPACE
:
Double click on this file to open it in RStudio; you will see the following:
Now, delete line 2, and then append a new line 3, as shown below. This will allow your tagged C++ interface files to be exportable to R. Leave line 4 blank, just as it is in the original. Then, save the file:
Remark: There are more advanced ways to configure the NAMESPACE
file when building an R package, which would require in-depth explanation, distracting us from the main task of getting up and running with Rcpp
. As such, we’ll just use this simple fix for our discussion.
Building an R Package
Returning to the Files
pane in the RStudio IDE (see Figure 5 above), note the following sudirectories:
man
: For documentation files (we will return to this in a later installment).R
: For R code to be included in a package; for now, we will only be concerned with C++ code.src
: This is where C++ code is located in the package:- Both header (
.h
) and implementation (.cpp
) files - Both interface and reusable C++ code files
- Both header (
By clicking on the src
subdirectory, you will see that there are two C++
files that are present by default in a blank RStudio Rcpp
project:
rcpp_hello_world.cpp
: Simple interface function included as an example, by default.RcppExports.cpp
: This is a C++ file that is generated each time theRcpp
project is built in the RStudio environment. You need not be concerned about its contents, but it is crucial that you never modify this file on your own.
The rcpp_hello_world.cpp
file
Let’s look at this simple example first. It should look somewhat similar to the C++ interface files presented last time. The main difference is it does not call any functions in an external file; it simply returns an R List
object to the function user in R. Note the // [[Rcpp::export]]
tag; this will export the rcpp_hello_world()
function to R:
#include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] List rcpp_hello_world() { CharacterVector x = CharacterVector::create( "foo", "bar" ) ; NumericVector y = NumericVector::create( 0.0, 1.0 ) ; List z = List::create( x, y ) ; return z ; }
Your First R Package with C++ Code
Now, let’s build the package with this single C++ function. To do this, from the Build
menu at the top of the RStudio IDE, and select Clean and Rebuild
. In the upper right hand pane in the IDE, you will then see the C++ being compiled, and the package being built.
When the build is complete, your R session will restart, and your package will be loaded into your current R session, as shown in the console at the bottom of the R Studio IDE:
Now, type in rcpp_hello_world()
at the console prompt, and check your results. You should see the following:
Congratulations! You have just built your first R package with integrated C++, and you called the exported function from an R session. You can also check that the package contents have been placed in the usual .../R-4.0.x/library
directory, in a subdirectory with the package name, just like any other R package you load from CRAN.
Distribute the Package as a Binary
You can also export the package in binary form to a .zip
file on Windows, or a tar.gz
file on the Mac or on Linux. To do this, again from the Build
menu, select Build Binary Package
.
You will again see the compile and build process in the upper right hand corner of the RStudio IDE. When complete, you can find your distributable file, e.g. RcppProject.zip
, in the directory one level up from your project directory. To deploy it, either copy it to another machine with the same OS and R setup, or delete the package subdirectory, e.g. .../R-4.0.x/library/RcppProject
. Then, open an new RStudio session, and install the package just as you would any other package locally:
\newpage
Next, load the package in your session, e.g. library(RcppProject)
, and then call the exported function again to verify it works.
Summary
We have now covered the process of building an R package containing C++ code in RStudio IDE, by integrating the code into an Rcpp
project. The C++ code in this case consisted of a single .cpp
file, with a single interface function tagged for export to R, to keep the discussion focused more on the process itself. Next time, we will revisit the C++ code file examples in the previous post, and show how to integrate them into an R package. The process is essentially the same as above, but with multiple source code files and multiple interface files, it will involve some additional management and other details.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.