0% found this document useful (0 votes)
14 views

RCPP Extending

This document provides an overview of how to extend the Rcpp package to work with custom C++ classes. It discusses both intrusive and non-intrusive approaches to extending the Rcpp::wrap and Rcpp::as conversion functions. Specializing templates, declaring conversion operators, and using macros are described as ways to integrate third-party types with Rcpp implicit conversions between R and C++ objects.

Uploaded by

Angel Argumedo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

RCPP Extending

This document provides an overview of how to extend the Rcpp package to work with custom C++ classes. It discusses both intrusive and non-intrusive approaches to extending the Rcpp::wrap and Rcpp::as conversion functions. Specializing templates, declaring conversion operators, and using macros are described as ways to integrate third-party types with Rcpp implicit conversions between R and C++ objects.

Uploaded by

Angel Argumedo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

Rcpp Extending

Dirk Eddelbuettela and Romain Françoisb


a
http://dirk.eddelbuettel.com; b https://romain.rbind.io/

This version was compiled on January 11, 2022

This note provides an overview of the steps programmers should follow to The Rcpp converter functions Rcpp::as and Rcpp::wrap are
extend Rcpp (Eddelbuettel et al., 2022; Eddelbuettel and François, 2011) extensible to user-defined types and third-party types.
for use with their own classes. This document is based on our experience
in extending Rcpp to work with the Armadillo (Sanderson, 2010) classes,
2. Extending Rcpp::wrap
available in the separate package RcppArmadillo (Eddelbuettel et al., 2021).
This document assumes knowledge of Rcpp as well as some knowledge of The Rcpp::wrap converter is extensible in essentially two ways :
C++ templates (Abrahams and Gurtovoy, 2004). intrusive and non-intrusive.

Rcpp | extending | R | C++


2.1. Intrusive extension. When extending Rcpp with your own
data type, the recommended way is to implement a conversion to
1. Introduction SEXP. This lets Rcpp::wrap know about the new data type. The
template meta programming (or TMP) dispatch is able to recognize
Rcpp facilitates data interchange between R and C++ through the
that a type is convertible to a SEXP and Rcpp::wrap will use that
templated functions Rcpp::as (for conversion of objects from R
conversion.
to C++) and Rcpp::wrap (for conversion from C++ to R). In other
The caveat is that the type must be declared before the main
words, we convert between the so-called S-expression pointers (in
header file Rcpp.h is included.
type SEXP) to a templated C++ type, and vice versa. The corre-
sponding function declarations are as follows: #include <RcppCommon.h>
// conversion from R to C++
class Foo {
template <typename T> T as(SEXP x);
public:
Foo();
// conversion from C++ to R
template <typename T> SEXP wrap(const T& object);
// this operator enables implicit Rcpp::wrap
operator SEXP();
These converters are often used implicitly, as in the following }
code chunk:
#include <Rcpp.h> #include <Rcpp.h>
using namespace Rcpp;
This is called intrusive because the conversion to SEXP operator
// [[Rcpp::export]] has to be declared within the class.
List fx(List input) { // we get a list from R
// pull std::vector<double> from R list 2.2. Non-intrusive extension. It is often desirable to offer automatic
// this is achieved through an implicit conversion to third-party types, over which the developer has no
// call to Rcpp::as control and can therefore not include a conversion to SEXP operator
std::vector<double> x = input["x"]; in the class definition.
To provide automatic conversion from C++ to R, one must de-
// return an R list; this is achieved clare a specialization of the Rcpp::wrap template between the
// through an implicit call to Rcpp::wrap includes of RcppCommon.h and Rcpp.h.
return List::create(_["front"] = x.front(),
_["back"] = x.back()); #include <RcppCommon.h>
}
// third party library that declares class Bar
Example:
#include <foobar.h>

# Run sourceCpp compilation to include file // declaring the specialization


# Rcpp::sourceCpp(file= "code.cpp") namespace Rcpp {
input <- list( x = seq(1, 10, by = 0.5) ) template <> SEXP wrap(const Bar&);
fx(input) }
# $front
# [1] 1 // this must appear after the specialization,
# // otherwise the specialization will not be
# $back // seen by Rcpp types
# [1] 10 #include <Rcpp.h>

https://cran.r-project.org/package=Rcpp Rcpp Vignette | January 11, 2022 | 1–3


It should be noted that only the declaration is required. The 3.2. Non-intrusive extension. It is also possible to fully specialize
implementation can appear after the Rcpp.h file is included, and Rcpp::as to enable non-intrusive implicit conversion capabilities.
therefore take full advantage of the Rcpp type system.
#include <RcppCommon.h>
Another non-intrusive option is to expose an external pointer.
The macro RCPP_EXPOSED_WRAP provides an easy way to expose
// third party library that declares class Bar
a C++ class to R as an external pointer. It can be used instead of
#include <foobar.h>
specializing Rcpp::wrap, and should not be used simultaneously.
Note that the C++ class has to use Rcpp modules. See the Rcpp
// declaring the specialization
modules vignette for more details.
namespace Rcpp {
#include <Rcpp.h> template <> Bar as(SEXP);
#include <foobar.h> }

RCPP_EXPOSED_WRAP(Bar) // this must appear after the specialization, or


// specialization will not be seen by Rcpp types
#include <Rcpp.h>
2.3. Templates and partial specialization. It is perfectly valid to
declare a partial specialization for the Rcpp::wrap template. The Furthermore, another non-intrusive option is to opt for sharing
compiler will identify the appropriate overload: an R external pointer. The macro RCPP_EXPOSED_AS provides an
easy way to extend Rcpp::as to expose R external pointers to C++.
#include <RcppCommon.h>
It can be used instead of specializing Rcpp::as, and should not
be used simultaneously. Note that the C++ class has to use Rcpp
// third party library that declares
modules. See the Rcpp modules vignette for more details.
// a template class Bling<T>
#include <foobar.h> #include <Rcpp.h>
#include <foobar.h>
// declaring the partial specialization
namespace Rcpp { RCPP_EXPOSED_AS(Bar)
namespace traits {
With this being said, there is one additional macro that
template <typename T> can be used to simultaneously define both Rcpp::wrap and
SEXP wrap(const Bling<T>&); Rcpp::as specialization for an external pointer. The macro
RCPP_EXPOSED_CLASS can be use to transparently exchange a class
} between R and C++ as an external pointer. Do not simultane-
} ously use it alongside RCPP_EXPOSED_AS, RCPP_EXPOSED_WRAP,
Rcpp::wrap, or Rcpp::as.
// this must appear after the specialization, or
// specialization will not be seen by Rcpp types 3.3. Templates and partial specialization. The signature of
#include <Rcpp.h> Rcpp::as does not allow partial specialization. When expos-
ing a templated class to Rcpp::as, the programmer must spe-
cialize the Rcpp::traits::Exporter template class. The TMP dis-
3. Extending Rcpp::as patch will recognize that a specialization of Exporter is avail-
able and delegate the conversion to this class. Rcpp defines the
Conversion from R to C++ is also possible in both intrusive and
non-intrusive ways.
Rcpp::traits::Exporter template class as follows :
namespace Rcpp {
3.1. Intrusive extension. As part of its template meta programming namespace traits {
dispatch logic, Rcpp::as will attempt to use the constructor of the
target class taking a SEXP. template <typename T> class Exporter{
public:
#include <RcppCommon.h>
Exporter(SEXP x) : t(x){}
inline T get() { return t; }
class Foo{
public:
private:
Foo();
T t;
};
// this ctor enables implicit Rcpp::as
}
Foo(SEXP);
}
}
This is the reason why the default behavior of Rcpp::as is to
// this must appear after the specialization, or
invoke the constructor of the type T taking a SEXP.
// specialization will not be seen by Rcpp types
Since partial specialization of class templates is allowed, we can
#include <Rcpp.h>
expose a set of classes as follows:

2 | https://cran.r-project.org/package=Rcpp Eddelbuettel and François


#include <RcppCommon.h>

// third party library that declares


// a template class Bling<T>
#include <foobar.h>

// declaring the partial specialization


namespace Rcpp {
namespace traits {
template <typename T>
class Exporter< Bling<T> >;
}
}

// this must appear after the specialization, or


// specialization will not be seen by Rcpp types
#include <Rcpp.h>

Using this approach, the requirements for the Exporter<


Bling<T> > class are:

• it should have a constructor taking a SEXP


• it should have a methods called get that returns an instance
of the Bling<T> type.

4. Summary
The Rcpp package greatly facilitates the transfer of objects between
R and C++. This note has shown how to extend Rcpp to either user-
defined or third-party classes via the Rcpp::as and Rcpp::wrap
template functions. Both intrusive and non-intrusive approaches
were discussed.

References
Abrahams D, Gurtovoy A (2004). C++ Template Metaprogramming: Concepts,
Tools and Techniques from Boost and Beyond. Addison-Wesley, Boston.
Eddelbuettel D, François R (2011). “Rcpp: Seamless R and C++
Integration.” Journal of Statistical Software, 40(8), 1–18. doi:
10.18637/jss.v040.i08. URL https://doi.org/10.18637/jss.v040.i08.
Eddelbuettel D, François R, Allaire J, Ushey K, Kou Q, Russel N, Chambers J,
Bates D (2022). Rcpp: Seamless R and C++ Integration. R package version
1.0.8, URL https://CRAN.R-Project.org/package=Rcpp.
Eddelbuettel D, François R, Bates D, Ni B (2021). RcppArmadillo: Rcpp in-
tegration for Armadillo templated linear algebra library. R package version
0.10.7.5.0, URL https://CRAN.R-Project.org/package=RcppArmadillo.
Sanderson C (2010). “Armadillo: An open source C++ Algebra Library for Fast
Prototyping and Computationally Intensive Experiments.” Technical report,
NICTA. URL https://arma.sf.net.

Eddelbuettel and François Rcpp Vignette | January 11, 2022 | 3

You might also like