R Package deal Integration with Fashionable Reusable C++ Code Utilizing Rcpp – Half 3

[This article was first published on R Views, and kindly contributed to R-bloggers]. (You’ll be able to report situation concerning the content material on this web page right here)


Wish to share your content material on R-bloggers? click on right here if in case you have a weblog, or right here in the event you do not.

Daniel Hanson is a full-time lecturer within the Computational Finance & Danger Administration program inside the Division of Utilized Arithmetic on the College of Washington.

Within the earlier put up on this collection, we checked out some design issues when integrating normal and reusable C++ code into an R bundle. Particular emphasis was on Rcpp’s function in facilitating a method of communication between R and the C++ code, significantly highlighting just a few of the C++ capabilities within the Rcpp namespace that conveniently and effectively move knowledge between an R numeric vector and a C++ std::vector object.

Right now, we’ll take a look at a particular instance of implementing the interface. We’ll see how one can configure code that enables the usage of normal reusable C++ in an R bundle, with out having to switch it with any R or Rcpp-specific syntax. It’s admittedly a easy and toy instance, however the objective is to offer a place to begin that may be simply prolonged for extra actual world examples.

The Code

To get began, let’s take a look on the code we’ll use for our demonstration. It’s damaged into three classes, per the design issues from the earlier put up:

  • Customary and reusable C++: No dependence on R or Rcpp
  • Interface stage C++: Makes use of capabilities within the Rcpp namespace
  • R capabilities exported by the interface stage: Identical names as within the interface stage

Customary and Reusable C++ Code

On this instance, we’ll use a small set of C++ non-member capabilities, and two lessons. There’s a declaration (header) file for the non-member capabilities, say NonmemberCppFcns.h, and one other with class declarations for 2 form lessons, Sq. and Circle, known as ConcreteShapes.h. Every of those is accompanied by a corresponding implementation file, with file extension .cpp, as one would possibly count on in a extra life like C++ code base.

Nonmember C++ Features

These capabilities are proven and described right here, as declared within the following C++ header file:

#embrace // Provides two actual numbers
double add(double x, double y);
// Types a vector of actual numbers and returns it
std::vector sortVec(std::vector v);
// Computes the product of the LCM and GCD of two integers, // utilizing C++17 capabilities std::lcm(.) and std::gcd(.)
int prodLcmGcd(int m, int n);

The final operate makes use of lately added options within the C++ Customary Library, to indicate that we will use C++17.

C++ Lessons

The 2 lessons in our reusable code base are declared within the ConcreteShapes.h file, as proven and described right here. Very similar to textbook C++ examples, we’ll write lessons for 2 geometric shapes, every with a member operate to compute the world of its corresponding object.

#embrace class Circle
{
public: Circle(double radius); // Computes the world of a circle with given radius double space() const; personal: double radius_;
};
class Sq.
{
public: Sq.(double aspect); // Computes the world of a sq. with given aspect size double space() const;
personal: double side_;
};

Interface Degree C++

Now, the following step is to make use of Rcpp, specifically for the next important duties:

  • Export the interface capabilities to R
  • Facilitate knowledge trade between R and C++ container objects

An interface file containing capabilities designated for export to R doesn’t require a header file with declarations; one can consider it as being analogous to a .cpp file that incorporates the important() operate in a C++ executable challenge. As well as, the interface will be contained in a single file, or cut up into a number of information. For demonstration, I’ve written two such information: CppInterface.cpp, which supplies the interface to the non-member capabilities above, and CppInterface2.cpp, which does the identical for the 2 C++ lessons.

Interface to Non-Member C++ Features:

Let’s first take a look the CppInterface.cpp interface file, which connects R with the nonmember capabilities in our C++ code base:

#embrace "NonmemberCppFcns.h"
#embrace #embrace // Nonmember Operate Interfaces:
// [[Rcpp::export]]
int rAdd(double x, double y)
{ // Name the add(.) operate within the reusable C++ code base: return add(x, y);
}
// [[Rcpp::export]]
Rcpp::NumericVector rSortVec(Rcpp::NumericVector v)
{ // Switch knowledge from NumericVector to std::vector auto stlVec = Rcpp::as>(v); // Name the reusable sortVec(.) operate, with the anticipated // std::vector argument: stlVec = sortVec(stlVec); // Reassign the outcomes from the vector return object // to the identical NumericVector v, utilizing Rcpp::wrap(.): v = Rcpp::wrap(stlVec); // Return as an Rcpp::NumericVector: return v;
}
// C++17 instance:
// [[Rcpp::export]]
int rProdLcmGcd(int m, int n)
{ return prodLcmGcd(m, n);
}
Included Declarations:

The NonmemberCppFcns.h declaration file is included on the prime with #embrace, simply as it might in a standalone C++ utility, in order that the interface will acknowledge these capabilities that reside within the reusable code base. The STL vector declaration is required, as we will quickly see. And, the important thing in making the interface work resides within the Rcpp.h file, which supplies entry to very helpful C++ capabilities within the Rcpp namespace.

Operate implementations:

Every of those capabilities is designated for export to R when the bundle is constructed, by putting the
// [[Rcpp::export]] tag simply above the every operate signature, as proven above. On this explicit instance, every interface operate merely calls a operate within the reusable code base. For instance, the rAdd(.) operate merely calls the add(.) operate within the reusable C++ code. Within the absence of a user-defined namespace, the interface operate identify have to be completely different from the operate it calls to forestall identify conflict errors through the construct, so I’ve merely chosen to prefix an r to the identify of every interface operate.

Observe that the rSort(.) operate takes in an Rcpp::NumericVector object, v. This kind will settle for knowledge handed in from R as a numeric vector and current it as a C++ object. Then, in order that we will name a operate in our code base, comparable to type(.), which expects a std::vector sort as its enter, Rcpp additionally supplies the Rcpp::as<.>(.) operate that facilitates the switch of knowledge from an Rcpp::NumericVector object to the STL container:

auto stlVec = Rcpp::as>(v);

Rcpp additionally offers us a operate that can switch knowledge from a std::vector sort being returned from our reusable C++ code again into an Rcpp::NumericVector, in order that the outcomes will be handed again to R as a well-known numeric vector sort:

v = Rcpp::wrap(stlVec);

Because the std::vector object is the workhorse C++ STL containers in quantitative work, these two Rcpp capabilities are a godsend.

Comment 1: There isn’t a rule that claims an interface operate can solely name a single operate within the reusable code; one can use whichever capabilities or lessons which are wanted to get the job carried out, similar to with some other C++ operate. I’ve merely stored it easy right here for demonstration functions.

Comment 2: The tag // [[Rcpp::plugins(cpp17)]] is usually positioned on the prime of a C++ supply file in on-line examples associated to Rcpp and C++17. I’ve not discovered this obligatory in my very own code, nonetheless, so long as the Makeconf file has been up to date for C++17, as described within the first put up on this collection.

Interface to C++ Lessons:

We now flip our consideration to the second interface file, CppInterface2.cpp, which connects R with the C++ lessons in our reusable code. It’s proven right here:

#embrace "ConcreteShapes.h"
// Class Member Operate Interfaces:
// Interface to Sq. member
// operate space(.):
// [[Rcpp::export]]
double squareArea(double aspect)
{ Sq. sq(aspect); return sq.space();
}
// Interface to Circle member
// operate space(.):
// [[Rcpp::export]]
double circleArea(double radius)
{ Circle circ(radius); return circ.space();
}

That is once more nothing terribly refined, however the excellent news is it reveals the method of making cases of lessons from the code base is just not troublesome in any respect. We first #embrace solely the header file containing these class declarations; Rcpp.h is just not required right here, as we’re not utilizing any capabilities within the the Rcpp namespace.

To compute the world of a sq., the aspect size is enter in R as a easy numeric sort and handed to the interface operate as a C++ double. The Sq. object, sq, is constructed with the aspect argument, and its space() member operate performs stated calculation and returns the consequence. The method is trivally comparable for the circleArea(.) operate.

R Features Exported by the Interface Degree

To wrap up this dialogue, let’s take a look at the capabilities an R consumer may have accessible after we construct the bundle in RStudio (coming subsequent on this collection). Every of those capabilities might be exported from their respective C++ interface capabilities as common R capabilities, specifically:

  • rAdd(.)
  • rSortVec(.)
  • rProdLcmGcd(.)
  • squareArea(.)
  • circleArea(.)

The bundle consumer won’t must know or care that the core calculations are being carried out in C++. Visually, we will symbolize the associations as proven within the following diagram:

Mapping R Package Functions to Reusable C++

Mapping R Package Functions to Reusable C++

The stable pink line represents a “Chinese language Wall” that separates our code base from the interface and permits us to take care of it as normal and reusable C++.

Abstract

This concludes our instance of configuring code that enables the usage of normal reusable C++ in an R bundle, with out having to switch it with any R or Rcpp-specific syntax. Within the subsequent put up, we’ll study how one can really construct this code into an R bundle by leveraging the comfort of Rcpp and RStudio, and deploy it for any variety of R customers. The supply code may also be made accessible with the intention to attempt it out for your self.

Leave a Reply

Your email address will not be published. Required fields are marked *