0% found this document useful (0 votes)
6 views3 pages

Extending Rcpp for Custom Classes

This document provides an overview of extending Rcpp to work with user-defined C++ types by specializing the Rcpp::wrap and Rcpp::as functions. There are intrusive and non-intrusive ways to extend both Rcpp::wrap and Rcpp::as. Intrusively, a type can implement an operator SEXP to enable conversion via Rcpp::wrap, or the programmer can specialize the Rcpp::wrap and Rcpp::as templates. Non-intrusively, the programmer can specialize just the Rcpp::wrap or Rcpp::as templates without modifying the third-party types. Templates can be partially specialized as well.

Uploaded by

David Moro
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views3 pages

Extending Rcpp for Custom Classes

This document provides an overview of extending Rcpp to work with user-defined C++ types by specializing the Rcpp::wrap and Rcpp::as functions. There are intrusive and non-intrusive ways to extend both Rcpp::wrap and Rcpp::as. Intrusively, a type can implement an operator SEXP to enable conversion via Rcpp::wrap, or the programmer can specialize the Rcpp::wrap and Rcpp::as templates. Non-intrusively, the programmer can specialize just the Rcpp::wrap or Rcpp::as templates without modifying the third-party types. Templates can be partially specialized as well.

Uploaded by

David Moro
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Rcpp Extending

Dirk Eddelbuettela and Romain Françoisb


a
[Link] b [Link]

This version was compiled on September 24, 2017

This note provides an overview of the steps programmers should follow to # [1] 10
extend Rcpp (Eddelbuettel et al., 2017a; Eddelbuettel and François, 2011)
for use with their own classes. This document is based on our expe- The Rcpp converter function Rcpp::as and Rcpp::wrap have
rience in extending Rcpp to work with the Armadillo (Sanderson, 2010) been designed to be extensible to user-defined types and third-party
classes, available in the separate package RcppArmadillo (Eddelbuettel types.
et al., 2017b). This document assumes knowledge of Rcpp as well as
some knowledge of C++ templates (Abrahams and Gurtovoy, 2004). 2. Extending Rcpp::wrap

Rcpp | extending | R | C++ The Rcpp::wrap converter is extensible in essentially two ways :
intrusive and non-intrusive.
1. Introduction 2.1. Intrusive extension. When extending Rcpp with your own
Rcpp facilitates data interchange between R and C++ through the data type, the recommended way is to implement a conversion to
templated functions Rcpp::as (for conversion of objects from R SEXP. This lets Rcpp::wrap know about the new data type. The
to C++) and Rcpp::wrap (for conversion from C++ to R). In other template meta programming (or TMP) dispatch is able to recognize
words, we convert between the so-called S-expression pointers (in that a type is convertible to a SEXP and Rcpp::wrap will use that
type SEXP) to a templated C++ type, and vice versa. The corre- conversion.
sponding function declarations are as follows: The caveat is that the type must be declared before the main
header file Rcpp.h is included.
// conversion from R to C++
template <typename T> T as(SEXP x); #include <RcppCommon.h>

// conversion from C++ to R class Foo {


template <typename T> SEXP wrap(const T& object); public:
Foo();
These converters are often used implicitly, as in the following
code chunk: // this operator enables implicit Rcpp::wrap
operator SEXP();
#include <Rcpp.h> }
using namespace Rcpp;
#include <Rcpp.h>
// [[Rcpp::export]]
List fx(List input) { // we get a list from R
This is called intrusive because the conversion to SEXP operator
// pull std::vector<double> from R list
has to be declared within the class.
// this is achieved through an implicit
// call to Rcpp::as 2.2. Non-intrusive extension. It is often desirable to offer auto-
std::vector<double> x = input["x"]; matic conversion to third-party types, over which the developer
has no control and can therefore not include a conversion to SEXP
// return an R list; this is achieved operator in the class definition.
// through an implicit call to Rcpp::wrap To provide automatic conversion from C++ to R, one must de-
return List::create(_["front"] = [Link](), clare a specialization of the Rcpp::wrap template between the
_["back"] = [Link]()); includes of RcppCommon.h and Rcpp.h.
}
#include <RcppCommon.h>
Example:
// third party library that declares class Bar
## Run sourceCpp compilation to include file
#include <foobar.h>
# Rcpp::sourceCpp(file= "[Link]")
input <- list( x = seq(1, 10, by = 0.5) )
// declaring the specialization
fx(input)
namespace Rcpp {
template <> SEXP wrap(const Bar&);
# $front }
# [1] 1
# // this must appear after the specialization,
# $back // otherwise the specialization will not be

[Link] Rcpp Vignette | September 24, 2017 | 1–3


// seen by Rcpp types #include <Rcpp.h>
#include <Rcpp.h>
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_EXPORT_WRAP provides an easy way to expose a // third party library that declares class Bar
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.
#include RcppCommon.h // declaring the specialization
#include foobar.h namespace Rcpp {
template <> Bar as(SEXP);
RCPP_EXPORT_WRAP(Bar); }

// this must appear after the specialization, or


2.3. Templates and partial specialization. It is perfectly valid to
// specialization will not be seen by Rcpp types
declare a partial specialization for the Rcpp::wrap template. The
#include <Rcpp.h>
compiler will identify the appropriate overload:
#include <RcppCommon.h> Furthermore, another non-intrusive option is to opt for sharing
an R external pointer. The macro RCPP_EXPORT_AS provides an
// third party library that declares easy way to extend Rcpp::as to expose R external pointers to C++.
// a template class Bling<T> It can be used instead of specializing Rcpp::as, and should not be
#include <foobar.h> used simultaneously.

// declaring the partial specialization #include RcppCommon.h


namespace Rcpp { #include foobar.h
namespace traits {
RCPP_EXPORT_AS(Bar);
template <typename T>
SEXP wrap(const Bling<T>&); With this being said, there is one additional macro that
can be used to simultaneously define both Rcpp::wrap and
} 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-
// this must appear after the specialization, or ously use it alongside RCPP_EXPOSED_AS, RCPP_EXPOSED_WRAP,
// specialization will not be seen by Rcpp types Rcpp::wrap, or Rcpp::as.
#include <Rcpp.h>
3.3. Templates and partial specialization. The signature of
Rcpp::as does not allow partial specialization. When expos-
3. Extending Rcpp::as ing a templated class to Rcpp::as, the programmer must spe-
Conversion from R to C++ is also possible in both intrusive and cialize the Rcpp::traits::Exporter template class. The TMP dis-
non-intrusive ways. patch will recognize that a specialization of Exporter is avail-
able and delegate the conversion to this class. Rcpp defines the
3.1. Intrusive extension. As part of its template meta programming Rcpp::traits::Exporter template class as follows :
dispatch logic, Rcpp::as will attempt to use the constructor of the
namespace Rcpp {
target class taking a SEXP.
namespace traits {
#include <RcppCommon.h>
template <typename T> class Exporter{
class Foo{ public:
public: Exporter(SEXP x) : t(x){}
Foo(); inline T get() { return t; }

// this ctor enables implicit Rcpp::as private:


Foo(SEXP); T t;
} };
}
}
// this must appear after the specialization, or
// specialization will not be seen by Rcpp types This is the reason why the default behavior of Rcpp::as is to
invoke the constructor of the type T taking a SEXP.

2 | [Link] Eddelbuettel and François


Since partial specialization of class templates is allowed, we can Using this approach, the requirements for the Exporter<
expose a set of classes as follows: Bling<T> > class are:
#include <RcppCommon.h> • it should have a constructor taking a SEXP
• it should have a methods called get that returns an instance
// third party library that declares of the Bling<T> type.
// a template class Bling<T>
#include <foobar.h>
4. Summary
// declaring the partial specialization The Rcpp package greatly facilitates the transfer of objects between
namespace Rcpp { R and C++. This note has shown how to extend Rcpp to either user-
namespace traits { defined or third-party classes via the Rcpp::as and Rcpp::wrap
template <typename T> template functions. Both intrusive and non-intrusive approaches
class Exporter< Bling<T> >; were discussed.
}
}

// this must appear after the specialization, or


// specialization will not be seen by Rcpp types
#include <Rcpp.h>
References 0.12.12, URL [Link]
Eddelbuettel D, François R, Bates D, Ni B (2017b). RcppArmadillo: Rcpp
Abrahams D, Gurtovoy A (2004). C++ Template Metaprogramming: Concepts,
integration for Armadillo templated linear algebra library. R package version
Tools and Techniques from Boost and Beyond. Addison-Wesley, Boston.
[Link].2, URL [Link]
Eddelbuettel D, François R (2011). “Rcpp: Seamless R and C++ Integration.”
Sanderson C (2010). “Armadillo: An open source C++ Algebra Library for Fast
Journal of Statistical Software, 40(8), 1–18. URL [Link]
Prototyping and Computationally Intensive Experiments.” Technical report,
i08/.
NICTA. URL [Link]
Eddelbuettel D, François R, Allaire J, Ushey K, Kou Q, Russel N, Chambers J,
Bates D (2017a). Rcpp: Seamless R and C++ Integration. R package version

Eddelbuettel and François Rcpp Vignette | September 24, 2017 | 3

Common questions

Powered by AI

Rcpp facilitates the use of C++ templated functions such as Rcpp::as and Rcpp::wrap to convert R data types by leveraging template metaprogramming to create generic functions that can handle multiple data types. For instance, Rcpp::as can convert an SEXP type from R to a specific C++ type using a template function. An example of such usage is converting an R list into a C++ std::vector by creating a List in R, passing it to a C++ function via Rcpp::sourceCpp, and then using Rcpp::as implicitly within the C++ function to handle the conversion. This process enables the seamless transfer of data types between R and C++, allowing for efficient interoperation of the two languages in computational tasks .

Partial specializations in Rcpp help manage conversions for templated classes by allowing specific templated class instances to be converted without directly altering their generic templates. This is done by specializing the Rcpp::traits::Exporter template class, which involves implementing a constructor taking a SEXP and a get method returning the desired type instance. This approach uses template metaprogramming to identify the appropriate template instances and perform conversions specifically tailored for those instances, thus providing flexibility in handling templated third-party types within the constraints of the Rcpp type conversion system .

Template metaprogramming in Rcpp is utilized to facilitate seamless data interchange between R and C++ by allowing the definition of templated converters like Rcpp::as and Rcpp::wrap. These templated functions are designed to handle automatic type conversion between R's S-expression pointers (SEXP) and C++ types. By leveraging template metaprogramming, Rcpp can dynamically determine if a C++ type is convertible to SEXP and vice versa, enabling efficient and type-safe conversions. This is achieved through both intrusive methods, such as defining type-specific conversion operators within a class, and non-intrusive methods, like creating template specializations for classes independent of their definitions .

Intrusive extensions offer the advantage of inherent integration within the class itself by defining methods such as a conversion operator to SEXP for a class. This allows the class to be directly recognized and processed by the Rcpp type system. The main benefit is the ability to customize how specific class types convert to R's SEXP for seamless integration and usage within R. It is particularly useful when the developer has control over the class definition, and it often results in more straightforward code maintenance by keeping the conversion logic contained within the class itself .

A significant challenge when extending Rcpp functionality for third-party templated C++ classes is ensuring the proper conversion mechanisms are in place without modifying the original class definition. Since partial template specialization in Rcpp::as is not feasible, developers must specialize the Rcpp::traits::Exporter template class to expose templated C++ classes to Rcpp. This involves defining the Exporter class with a constructor accepting an SEXP and a get method returning the templated type. These solutions allow for non-intrusive handling of template classes within Rcpp, enabling their seamless integration into R while maintaining the integrity and structure of external libraries .

The Rcpp::as function is limited in that it does not support partial specialization, which restricts its direct use with templated classes. Rcpp addresses this limitation by providing the Rcpp::traits::Exporter template class, which allows developers to define full specializations for specific templated classes. The Exporter class must have a constructor that initializes using an SEXP and a method called get to return the specialized type instance. This mechanism allows Rcpp to manage conversions for complex template types, overcoming the limitations of Rcpp::as regarding partial specialization by providing a structured approach to handle such cases effectively .

The Rcpp::wrap converter can be extended using either intrusive or non-intrusive methods. The intrusive extension involves declaring a conversion operator to SEXP within the class definition itself, which is recognized by the Rcpp type system. This method requires modifications to the original class definition to accommodate the conversion. On the other hand, non-intrusive extension does not require altering the original class definition. Instead, it is achieved by declaring a specialization of the Rcpp::wrap template between the includes of RcppCommon.h and Rcpp.h, allowing third-party types to be converted without modifying their source code .

Declaring Rcpp specializations between specific include directives, such as between RcppCommon.h and Rcpp.h, ensures that the templated conversion functions are recognized and processed correctly by the Rcpp type system. This order is crucial because it allows the compiler to register the template specializations before the main Rcpp header, which maps R and C++ types. Failing to follow this order could result in the specialization not being seen by Rcpp types, leading to compile-time errors or incorrect type conversions as the dispatch system might default to other available conversion mechanisms .

To provide non-intrusive extensions for Rcpp::as, a developer must create a full specialization of the Rcpp::as template function for the specific class type. This method does not alter the original class but requires the developer to declare the specialization for the Rcpp::as function between the includes of RcppCommon.h and Rcpp.h. Another approach is to use RCPP_EXPORT_AS to expose a third-party or built-in type as an external pointer, which simplifies the process but is mutually exclusive with the specialization approach. Developers must be careful to ensure that the specialization is declared between these includes and that the implementation is placed appropriately after including the Rcpp.h file to leverage the Rcpp type system effectively .

The macro RCPP_EXPORT_WRAP is used in Rcpp to expose a C++ class to R as an external pointer, which means the class can be referred to in R with a pointer without needing additional interface code for conversion. This provides a straightforward mechanism to extend Rcpp::wrap functionality non-intrusively for third-party types, meaning the class definition does not need modification. It should not be used simultaneously with other specialization methods because these techniques, like fully specializing Rcpp::wrap, could conflict with how pointers are handled and lead to ambiguous or redundant conversion mechanisms that could complicate data handling and consistency .

You might also like