Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
37 views

RCPP Extending

This document provides an overview of how to extend Rcpp to work with custom C++ types. There are two main approaches: intrusive, which involves implementing conversion operators directly in the custom class, and non-intrusive, which uses template specialization or macros to enable conversion without modifying the custom class. The recommended intrusive approach is to add an operator to convert instances to SEXP pointers, while non-intrusive options include specializing the Rcpp::wrap and Rcpp::as templates or using exposure macros.

Uploaded by

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

RCPP Extending

This document provides an overview of how to extend Rcpp to work with custom C++ types. There are two main approaches: intrusive, which involves implementing conversion operators directly in the custom class, and non-intrusive, which uses template specialization or macros to enable conversion without modifying the custom class. The recommended intrusive approach is to add an operator to convert instances to SEXP pointers, while non-intrusive options include specializing the Rcpp::wrap and Rcpp::as templates or using exposure macros.

Uploaded by

ulysses_lp
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 November 8, 2019

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., 2019a; 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 expe-
rience in extending Rcpp to work with the Armadillo (Sanderson, 2010)
2. Extending Rcpp::wrap
classes, available in the separate package RcppArmadillo (Eddelbuettel
et al., 2019b). This document assumes knowledge of Rcpp as well as The Rcpp::wrap converter is extensible in essentially two ways :
some knowledge of 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 auto-
// this is achieved through an implicit matic conversion to third-party types, over which the developer
// call to Rcpp::as has no control and can therefore not include a conversion to SEXP
std::vector<double> x = input["x"]; operator 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 | November 8, 2019 | 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. URL http://www.jstatsoft.org/v40/
i08/.
Eddelbuettel D, François R, Allaire J, Ushey K, Kou Q, Russel N, Chambers J,
Bates D (2019a). Rcpp: Seamless R and C++ Integration. R package version
1.0.3, URL http://CRAN.R-Project.org/package=Rcpp.
Eddelbuettel D, François R, Bates D, Ni B (2019b). RcppArmadillo: Rcpp
integration for Armadillo templated linear algebra library. R package version
0.9.800.1.0, URL http://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 http://arma.sf.net.

Eddelbuettel and François Rcpp Vignette | November 8, 2019 | 3

You might also like