[Rcpp-commits] r2988 - in pkg/Rcpp: R inst/doc

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Apr 11 11:45:14 CEST 2011


Author: romain
Date: 2011-04-11 11:45:14 +0200 (Mon, 11 Apr 2011)
New Revision: 2988

Modified:
   pkg/Rcpp/R/loadRcppModules.R
   pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
Log:
so that we dont use tail (from utils)

Modified: pkg/Rcpp/R/loadRcppModules.R
===================================================================
--- pkg/Rcpp/R/loadRcppModules.R	2011-04-11 09:34:06 UTC (rev 2987)
+++ pkg/Rcpp/R/loadRcppModules.R	2011-04-11 09:45:14 UTC (rev 2988)
@@ -7,7 +7,7 @@
    } ) )
    if( !length(w) ) 
     stop( "loadRcppModules can only be used within a .onLoad function" )
-   w <- tail( w, 1L )
+   w <- w[ length(w) ]
    call <- calls[[w]]
    if( !identical( call[[2L]], ".onLoad" ) ) 
     stop( "loadRcppModules can only be used within a .onLoad function" )

Modified: pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-modules.Rnw	2011-04-11 09:34:06 UTC (rev 2987)
+++ pkg/Rcpp/inst/doc/Rcpp-modules.Rnw	2011-04-11 09:45:14 UTC (rev 2988)
@@ -1,4 +1,1177 @@
 \documentclass[10pt]{article}
 %\VignetteIndexEntry{Rcpp-modules}
+\usepackage{vmargin}
+\setmargrb{0.75in}{0.75in}{0.75in}{0.75in}
+
+\usepackage{color, alltt}
+\usepackage[authoryear,round,longnamesfirst]{natbib}
+\usepackage[colorlinks]{hyperref}
+\definecolor{link}{rgb}{0,0,0.3}	%% next few lines courtesy of RJournal.sty
+\hypersetup{
+    colorlinks,%
+    citecolor=link,%
+    filecolor=link,%
+    linkcolor=link,%
+    urlcolor=link
+}
+
+\newcommand{\proglang}[1]{\textsf{#1}}
+\newcommand{\pkg}[1]{{\fontseries{b}\selectfont #1}}
+
+<<echo=FALSE,print=FALSE>>=
+require( inline )
+require( Rcpp )
+prettyVersion <- packageDescription("Rcpp")$Version
+prettyDate <- format(Sys.Date(), "%B %e, %Y")
+@
+
+\author{Dirk Eddelbuettel \and Romain Fran\c{c}ois}
+\title{Exposing \proglang{C++} functions and classes with \pkg{Rcpp} modules}
+\date{\pkg{Rcpp} version \Sexpr{prettyVersion} as of \Sexpr{prettyDate}}
+
+<<echo=FALSE>>=
+link <- function( f, package, text = f, root = "http://finzi.psych.upenn.edu/R/library/" ) {
+	h <- if( missing(package) ) {
+		as.character( help( f ) )
+	} else {
+		as.character( help( f, package = paste( package, sep = "" ) ) )
+	}
+	if( ! length(h) ) {
+		sprintf( "\\\\textbf{%s}", f )
+	} else {
+		rx <- "^.*/([^/]*?)/help/(.*?)$"
+		package <- sub( rx, "\\1", h, perl = TRUE )
+		page <- sub( rx, "\\2", h, perl = TRUE )
+		sprintf( "\\\\href{%s%s/html/%s.html}{\\\\texttt{%s}}", root, package, page, text )
+	}
+}
+linkS4class <- function( cl, package, text = cl, root = "http://finzi.psych.upenn.edu/R/library/" ) {
+	link( sprintf("%s-class", cl), package, text, root )
+}
+@
+
 \begin{document}
+\maketitle
+
+\abstract{
+  \noindent
+  This note discusses \textsl{Rcpp modules}. \textsl{Rcpp modules} allow programmers to
+  expose \proglang{C++} functions and classes to \proglang{R} with relative
+  ease.  \textsl{Rcpp modules} are inspired from the \pkg{Boost.Python}
+  \proglang{C++} library \citep{Abrahams+Grosse-Kunstleve:2003:Boost.Python}
+  which provides similar features for \proglang{Python}.
+}
+
+\section{Motivation}
+
+Exposing \proglang{C++} functionality to \proglang{R} is greatly facilitated
+by the \pkg{Rcpp} package and its underlying \proglang{C++} library
+\citep{CRAN:Rcpp}. \pkg{Rcpp} smoothes many of the rough edges in
+\proglang{R} and \proglang{C++} integration by replacing the traditional
+\proglang{R} Application Programming Interface (API) described in
+`\textsl{Writing R Extensions}' \citep{R:Extensions} with a consistent set of \proglang{C++}
+classes. The `\textsl{Rcpp-introduction}' vignette \citep{CRAN:Rcpp} describes the API and
+provides an introduction to using \pkg{Rcpp}.
+
+These \pkg{Rcpp} facilities offer a lot of assistance to the programmer
+wishing to interface \proglang{R} and \proglang{C++}. At the same time, these
+facilities are limited as they operate on a function-by-function basis. The
+programmer has to implement a \Sexpr{link(".Call")} compatible function (to
+conform to the \proglang{R} API) using classes of the \pkg{Rcpp} API as
+described in the next section.
+
+\subsection{Exposing functions using \pkg{Rcpp}}
+
+Exposing existing \proglang{C++} functions to \proglang{R} through \pkg{Rcpp}
+usually involves several steps. One approach is to write an additional wrapper
+function that is responsible for converting input objects to the appropriate
+types, calling the actual worker function and converting the results back to
+a suitable type that can be returned to \proglang{R} (\texttt{SEXP}).
+Consider the \texttt{norm} function below:
+
+<<lang=cpp>>=
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+@
+
+This simple function does not meet the requirements set by the \texttt{.Call}
+convention, so it cannot be called directly by \proglang{R}. Exposing the
+function involves writing a simple wrapper function
+that does match the \texttt{.Call} requirements. \pkg{Rcpp} makes this easy.
+
+<<lang=cpp>>=
+using namespace Rcpp;
+RcppExport SEXP norm_wrapper(SEXP x_, SEXP y_) {
+    // step 0: convert input to C++ types
+    double x = as<double>(x_), y = as<double>(y_);
+
+    // step 1: call the underlying C++ function
+    double res = norm( x, y );
+
+    // step 2: return the result as a SEXP
+    return wrap( res );
+}
+@
+
+Here we use the (templated) \pkg{Rcpp} converter \texttt{as()} which can
+transform from a \texttt{SEXP} to a number of different \proglang{C++} and
+\pkg{Rcpp} types. The \pkg{Rcpp} function \texttt{wrap()} offers the opposite
+functionality and converts many known types to a \texttt{SEXP}.
+
+This process is simple enough, and is used by a number of CRAN packages.
+However, it requires direct involvement from the programmer, which quickly
+becomes tiresome when many functions are involved. \textsl{Rcpp modules}
+provides a much more elegant and unintrusive way to expose \proglang{C++}
+functions such as the \texttt{norm} function shown above to \proglang{R}.
+
+\subsection{Exposing classes using Rcpp}
+
+Exposing \proglang{C++} classes or structs is even more of a challenge because it
+requires writing glue code for each member function that is to be exposed.
+
+Consider the simple \texttt{Uniform} class below:
+
+<<lang=cpp>>=
+class Uniform {
+public:
+    Uniform(double min_, double max_) : min(min_), max(max_) {}
+
+    NumericVector draw(int n) {
+        RNGScope scope;
+        return runif( n, min, max );
+    }
+
+private:
+    double min, max;
+};
+@
+
+To use this class from R, we at least need to expose the constructor and
+the \texttt{draw} method. External pointers
+\citep{R:Extensions} are the perfect vessel for this, and using the
+\texttt{Rcpp:::XPtr} template from \pkg{Rcpp} we can expose the class
+with these two functions:
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+/// create an external pointer to a Uniform object
+RcppExport SEXP Uniform__new(SEXP min_, SEXP max_) {
+    // convert inputs to appropriate C++ types
+    double min = as<double>(min_), max = as<double>(max_);
+
+    // create a pointer to an Uniform object and wrap it
+    // as an external pointer
+    Rcpp::XPtr<Uniform> ptr( new Uniform( min, max ), true );
+
+    // return the external pointer to the R side
+    return ptr;
+}
+
+/// invoke the draw method
+RcppExport SEXP Uniform__draw( SEXP xp, SEXP n_ ) {
+    // grab the object as a XPtr (smart pointer) to Uniform
+    Rcpp::XPtr<Uniform> ptr(xp);
+
+    // convert the parameter to int
+    int n = as<int>(n_);
+
+    // invoke the function
+    NumericVector res = ptr->draw( n );
+
+    // return the result to R
+    return res;
+}
+@
+
+As it is generally a bad idea to expose external pointers `as is',
+they usually get wrapped as a slot of an S4 class.
+
+<<echo=FALSE,results=hide>>=
+f1 <- cxxfunction( , "", includes = '
+using namespace Rcpp;
+
+class Uniform {
+public:
+    Uniform(double min_, double max_) : min(min_), max(max_) {}
+
+    NumericVector draw(int n) {
+        RNGScope scope;
+        return runif( n, min, max );
+    }
+
+private:
+    double min, max;
+};
+
+/// create an external pointer to a Uniform object
+RcppExport SEXP Uniform__new(SEXP min_, SEXP max_) {
+    // convert inputs to appropriate C++ types
+    double min = as<double>(min_), max = as<double>(max_);
+
+    // create a pointer to an Uniform object and wrap it
+    // as an external pointer
+    Rcpp::XPtr<Uniform> ptr( new Uniform( min, max ), true );
+
+    // return the external pointer to the R side
+    return ptr;
+}
+
+/// invoke the draw method
+RcppExport SEXP Uniform__draw( SEXP xp, SEXP n_ ) {
+    // grab the object as a XPtr (smart pointer) to Uniform
+    Rcpp::XPtr<Uniform> ptr(xp);
+
+    // convert the parameter to int
+    int n = as<int>(n_);
+
+    // invoke the function
+    NumericVector res = ptr->draw( n );
+
+    // return the result to R
+    return res;
+}
+', plugin = "Rcpp" )
+getDynLib( f1 )
+@
+
+<<>>=
+setClass( "Uniform", representation( pointer = "externalptr" ) )
+
+# helper
+Uniform_method <- function(name) {
+    paste( "Uniform", name, sep = "__" )
+}
+
+# syntactic sugar to allow object$method( ... )
+setMethod( "$", "Uniform", function(x, name ) {
+    function(...) .Call( Uniform_method(name) , x at pointer, ... )
+} )
+# syntactic sugar to allow new( "Uniform", ... )
+setMethod( "initialize", "Uniform", function(.Object, ...) {
+    .Object at pointer <- .Call( Uniform_method("new"), ... )
+    .Object
+} )
+
+u <- new( "Uniform", 0, 10 )
+u$draw( 10L )
+@
+
+\pkg{Rcpp} considerably simplifies the code that would
+be involved for using external pointers with the traditional \proglang{R} API.
+Yet this still involves a lot of mechanical code that quickly
+becomes hard to maintain and error prone.
+\textsl{Rcpp modules} offer an elegant way to expose the \texttt{Uniform}
+class in a way that makes both the internal
+\proglang{C++} code and the \proglang{R} code easier.
+
+
+
+\section{Rcpp modules}
+
+The design of Rcpp modules has been influenced by \proglang{Python} modules which are generated by the
+\texttt{Boost.Python} library \citep{Abrahams+Grosse-Kunstleve:2003:Boost.Python}.
+Rcpp modules provide a convenient and easy-to-use way
+to expose \proglang{C++} functions and classes to \proglang{R}, grouped
+together in a single entity.
+
+A Rcpp module is created in a \texttt{cpp} file using the \texttt{RCPP\_MODULE}
+macro, which then provides declarative code of what the module
+exposes to \proglang{R}.
+
+\subsection{Exposing \proglang{C++} functions using Rcpp modules}
+
+Consider the \texttt{norm} function from the previous section.
+We can expose it to \proglang{R} :
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod) {
+    function( "norm", &norm );
+}
+@
+
+The code creates an Rcpp module called \texttt{mod}
+that exposes the \texttt{norm} function. \pkg{Rcpp} automatically
+deduces the conversions that are needed for input and output. This alleviates
+the need for a wrapper function using either \pkg{Rcpp} or the \proglang{R} API.
+
+On the \proglang{R} side, the module is retrieved by using the
+\Sexpr{link("Module")} function from \pkg{Rcpp}:
+
+<<eval=FALSE>>=
+require( Rcpp )
+mod <- Module( "mod" )
+mod$norm( 3, 4 )
+@
+
+A module can contain any number of calls to \texttt{function} to register
+many internal functions to \proglang{R}. For example, these 6 functions :
+
+<<lang=cpp>>=
+std::string hello() {
+    return "hello";
+}
+
+int bar( int x) {
+    return x*2;
+}
+
+double foo( int x, double y) {
+    return x * y;
+}
+
+void bla( ) {
+    Rprintf( "hello\\n" );
+}
+
+void bla1( int x) {
+    Rprintf( "hello (x = %d)\\n", x );
+}
+
+void bla2( int x, double y) {
+    Rprintf( "hello (x = %d, y = %5.2f)\\n", x, y );
+}
+@
+
+It can be exposed with the following minimal code:
+
+<<lang=cpp>>=
+RCPP_MODULE(yada) {
+    using namespace Rcpp;
+
+    function( "hello" , &hello );
+    function( "bar"   , &bar   );
+    function( "foo"   , &foo   );
+    function( "bla"   , &bla   );
+    function( "bla1"  , &bla1   );
+    function( "bla2"  , &bla2   );
+}
+@
+
+and can then be used from \proglang{R}:
+
+<<eval=FALSE>>=
+require( Rcpp )
+
+yada <- Module( "yada" )
+yada$bar( 2L )
+yada$foo( 2L, 10.0 )
+yada$hello()
+yada$bla()
+yada$bla1( 2L)
+yada$bla2( 2L, 5.0 )
+@
+
+The requirements for a function to be exposed to \proglang{R} via Rcpp modules
+are:
+\begin{itemize}
+\item The function takes between 0 and 65 parameters.
+\item The type of each input parameter must be manageable by the \texttt{Rcpp::as}
+template.
+\item The return type of the function must be either \texttt{void} or any type that
+can be managed by the \texttt{Rcpp::wrap} template.
+\item The function name itself has to be unique in the module.
+  In other words, no two functions with
+  the same name but different signatures are allowed. C++ allows overloading
+  functions. This might be added in future versions of modules.
+\end{itemize}
+
+\subsubsection{Documentation for exposed functions using Rcpp modules}
+
+In addition to the name of the function and the function pointer, it is possible
+to pass a short description of the function as the third parameter of \texttt{function}.
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod) {
+    function( "norm", &norm, "Provides a simple vector norm" );
+}
+@
+
+The description is used when displaying the function to the R prompt:
+
+<<echo=FALSE>>=
+fx <- cxxfunction( , "", includes = '
+
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod) {
+    function( "norm", &norm, "Provides a simple vector norm" );
+}
+', plugin = "Rcpp" )
+mod <- Module( "mod", getDynLib( fx ) )
+@
+<<>>=
+show( mod$norm )
+@
+
+\subsubsection{Formal arguments specification}
+
+\texttt{function} also gives the possibility to specify the formal arguments
+of the R function that encapsulates the C++ function, by passing
+a \texttt{Rcpp::List} after the function pointer.
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals) {
+     function( "norm",
+              &norm,
+              List::create( _["x"] = 0.0, _["y"] = 0.0 ),
+              "Provides a simple vector norm");
+}
+@
+
+A simple usage example is provided below:
+
+<<echo=FALSE,results=hide>>=
+fx_form <- cxxfunction( , '', includes = '
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals) {
+     function( "norm", &norm,
+              List::create( _["x"] = 0.0, _["y"] = 0.0 ),
+              "Provides a simple vector norm");
+}
+', plugin = "Rcpp" )
+mod <- Module( "mod_formals", getDynLib( fx_form ), mustStart = TRUE )
+@
+<<>>=
+norm <- mod$norm
+norm()
+norm( y = 2 )
+norm( x = 2, y = 3 )
+args( norm )
+@
+
+To set formal arguments without default values, simply omit the rhs.
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals2) {
+    function( "norm", &norm,
+             List::create( _["x"], _["y"] = 0.0 ),
+             "Provides a simple vector norm");
+}
+@
+
+This can be used as follows:
+
+<<echo=FALSE,results=hide>>=
+fx_form2 <- cxxfunction( , '', includes = '
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals2) {
+        function( "norm", &norm,
+                 List::create( _["x"], _["y"] = 0.0 ),
+                 "Provides a simple vector norm");
+}
+', plugin = "Rcpp" )
+mod <- Module( "mod_formals2", getDynLib( fx_form2 ), mustStart = TRUE )
+@
+<<>>=
+norm <- mod$norm
+args( norm )
+@
+
+The ellipsis (\texttt{...}) can be used to denote that additional arguments
+are optional; it does not take a default value.
+
+<<lang=cpp>>=
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals3) {
+    function( "norm", &norm,
+             List::create( _["x"], _["..."] ),
+             "documentation for norm");
+}
+@
+<<echo=FALSE,results=hide>>=
+fx_form3 <- cxxfunction( , '', includes = '
+using namespace Rcpp;
+
+double norm( double x, double y ) {
+    return sqrt( x*x + y*y );
+}
+
+RCPP_MODULE(mod_formals3) {
+    function( "norm", &norm,
+             List::create( _["x"] , _["..."]  ),
+             "documentation for norm");
+}
+', plugin = "Rcpp" )
+mod <- Module( "mod_formals3", getDynLib( fx_form3 ), mustStart = TRUE )
+@
+<<>>=
+norm <- mod$norm
+args( norm )
+@
+
+
+\subsection{Exposing \proglang{C++} classes using Rcpp modules}
+
+Rcpp modules also provide a mechanism for exposing \proglang{C++} classes, based
+on the reference classes introduced in R 2.12.0.
+
+\subsubsection{Initial example}
+
+A class is exposed using the \texttt{class\_} keyword. The \texttt{World}
+class may be exposed to \proglang{R} as follows:
+
+<<lang=cpp>>=
+using namespace Rcpp;
+class Uniform {
+public:
+    Uniform(double min_, double max_) : min(min_), max(max_) {}
+
+    NumericVector draw(int n) const {
+        RNGScope scope;
+        return runif( n, min, max );
+    }
+
+    double min, max;
+};
+
+double range( Uniform* w) {
+    return w->max - w->min;
+}
+
+RCPP_MODULE(unif_module) {
+
+    class_<Uniform>( "Uniform" )
+
+    .constructor<double,double>()
+
+    .field( "min", &Uniform::min )
+    .field( "max", &Uniform::max )
+
+    .method( "draw", &World::draw )
+    .method( "range", &range )
+    ;
+
+}
+@
+
+<<results=hide,echo=FALSE>>=
+fx_unif <- cxxfunction( , "", includes = '
+using namespace Rcpp;
+class Uniform {
+public:
+    Uniform(double min_, double max_) : min(min_), max(max_) {}
+
+    NumericVector draw(int n) const {
+        RNGScope scope;
+        return runif( n, min, max );
+    }
+
+    double min, max;
+};
+
+double range( Uniform* w) {
+    return w->max - w->min;
+}
+
+RCPP_MODULE(unif_module) {
+
+    class_<Uniform>( "Uniform" )
+
+    .constructor<double,double>()
+
+    .field( "min", &Uniform::min )
+    .field( "max", &Uniform::max )
+
+    .method( "draw", &Uniform::draw )
+    .method( "range", &range )
+    ;
+
+}
+', plugin = "Rcpp" )
+unif_module <- Module( "unif_module", getDynLib(fx_unif ) )
+@
+<<>>=
+Uniform <- unif_module$Uniform
+u <- new( Uniform, 0, 10 )
+u$draw( 10L )
+u$range()
+u$max <- 1
+u$range()
+u$draw( 10 )
+@
+
+\texttt{class\_} is templated by the \proglang{C++} class or struct
+that is to be exposed to \proglang{R}.
+The parameter of the \texttt{class\_<Uniform>} constructor is the name we will
+use on the \proglang{R} side. It usually makes sense to use the same name as the class
+name. While this is not enforced, it might be useful when exposing a class
+generated from a template.
+
+Then constructors, fields and methods are exposed.
+
+\subsubsection{Exposing constructors using Rcpp modules}
+
+Public constructors that take from 0 and 6 parameters can be exposed
+to the R level using the \texttt{.constuctor} template method of \texttt{.class\_}.
+
+Optionally, \texttt{.constructor} can take a description as the first argument.
+
+<<lang=cpp>>=
+    .constructor<double,double>("sets the min and max value of the distribution")
+@
+
+Also, the second argument can be a function pointer (called validator)
+matching the following type :
+
+<<lang=cpp>>=
+typedef bool (*ValidConstructor)(SEXP*,int);
+@
+
+The validator can be used to implement dispatch to the appropriate constructor,
+when multiple constructors taking the same number of arguments are exposed.
+The default validator always accepts the constructor as valid if it is passed
+the appropriate number of arguments. For example, with the call above, the default
+validator accepts any call from R with two \texttt{double} arguments (or
+arguments that can be cast to \texttt{double}).
+
+TODO: include validator example here
+
+\subsubsection{Exposing fields and properties}
+
+\texttt{class\_} has three ways to expose fields and properties, as
+illustrated in the example below :
+
+<<lang=cpp>>=
+using namespace Rcpp;
+class Foo {
+    public:
+        Foo( double x_, double y_, double z_ ):
+            x(x_), y(y_), z(z_) {}
+
+        double x;
+        double y;
+
+        double get_z() { return z; }
+        void set_z( double z_ ) { z = z_; }
+
+    private:
+        double z;
+};
+
+RCPP_MODULE(mod_foo) {
+    class_<Foo>( "Foo" )
+
+    .constructor<double,double,double>()
+
+    .field( "x", &Foo::x )
+    .field_readonly( "y", &Foo::y )
+
+    .property( "z", &Foo::get_z, &Foo::set_z )
+    ;
+}
+@
+
+The \texttt{.field} method exposes a public field with read/write access from R.
+\texttt{field} accepts an extra parameter to give a short description of the
+field:
+
+<<lang=cpp>>=
+    .field( "x", &Foo::x, "documentation for x" )
+@
+
+The \texttt{.field\_readonly} exposes a public field with read-only access from R.
+It also accepts the description of the field.
+
+<<lang=cpp>>=
+    .field_readonly( "y", &Foo::y, "documentation for y" )
+@
+
+The \texttt{.property} method allows indirect access to fields through
+a getter and a setter. The setter is optional, and the property is considered
+read-only if the setter is not supplied. A description of the property is also
+allowed:
+
+<<lang=cpp>>=
+    // with getter and setter
+    .property( "z", &Foo::get_z, &Foo::set_z, "Documentation for z" )
+
+    // with only getter
+    .property( "z", &Foo::get_z, "Documentation for z" )
+@
+
+The type of the field (\textbf{T}) is deduced from the return type of the getter, and if a
+setter is given its unique parameter should be of the same type.
+
+Getters can be member functions taking no parameter and returning a \textbf{T}
+(for example \texttt{get\_z} above), or
+a free function taking a pointer to the exposed
+class and returning a \textbf{T}, for example:
+
+<<lang=cpp>>=
+double z_get( Foo* foo ) { return foo->get_z(); }
+@
+
+Setters can be either a member function taking a \texttt{T} and returning void, such
+as \texttt{set\_z} above, or a free function taking a pointer to the target
+class and a \textbf{T} :
+
+<<lang=cpp>>=
+void z_set( Foo* foo, double z ) { foo->set_z(z); }
+@
+
+Using properties gives more flexibility in case field access has to be tracked
+or has impact on other fields. For example, this class keeps track of how many times
+the \texttt{x} field is read and written.
+
+<<lang=cpp>>=
+class Bar {
+    public:
+
+        Bar(double x_) : x(x_), nread(0), nwrite(0) {}
+
+        double get_x( ) {
+            nread++;
+            return x;
+        }
+
+        void set_x( double x_) {
+            nwrite++;
+            x = x_;
+        }
+
+        IntegerVector stats() const {
+            return IntegerVector::create(
+                _["read"] = nread,
+                _["write"] = nwrite
+            );
+        }
+
+    private:
+        double x;
+        int nread, nwrite;
+}
+RCPP_MODULE(mod_bar) {
+    class_<Bar>( "Bar" )
+
+    .constructor<double>()
+
+    .property( "x", &Bar::get_x, &Bar::set_x )
+    .method( "stats", &Bar::stats )
+    ;
+}
+@
+
+Here is a simple usage example:
+
+<<echo=FALSE,results=hide>>=
+fx_bar <- cxxfunction( , "", includes = '
+class Bar {
+    public:
+
+        Bar(double x_) : x(x_), nread(0), nwrite(0) {}
+
+        double get_x( ) {
+            nread++;
+            return x;
+        }
+
+        void set_x( double x_) {
+            nwrite++;
+            x = x_;
+        }
+
+        IntegerVector stats() const {
+            return IntegerVector::create(
+                _["read"] = nread,
+                _["write"] = nwrite
+            );
+        }
+
+    private:
+        double x;
+        int nread, nwrite;
+};
+
+RCPP_MODULE(mod_bar) {
+    class_<Bar>( "Bar" )
+
+        .constructor<double>()
+
+        .property( "x", &Bar::get_x, &Bar::set_x )
+        .method( "stats", &Bar::stats )
+    ;
+}
+', plugin = "Rcpp" )
+mod_bar <- Module( "mod_bar", getDynLib( fx_bar ) )
+@
+<<>>=
+Bar <- mod_bar$Bar
+b <- new( Bar, 10 )
+b$x + b$x
+b$stats()
+b$x <- 10
+b$stats()
+@
+
+\subsubsection{Exposing methods using Rcpp modules}
+
+\texttt{class\_} has several overloaded and templated \texttt{.method}
+functions allowing the programmer to expose a method associated with the class.
+
+A legitimate method to be exposed by \texttt{.method} can be:
+\begin{itemize}
+\item A public member function of the class, either const or non const, that
+returns void or any type that can be handled by \texttt{Rcpp::wrap}, and that
+takes between 0 and 65 parameters whose types can be handled by \texttt{Rcpp::as}.
+\item A free function that takes a pointer to the target class as its first
+parameter, followed by 0 or more (up to 65) parameters that can be handled by
+\texttt{Rcpp::as} and returning a type that can be handled by \texttt{Rcpp::wrap}
+or void.
+\end{itemize}
+
+\paragraph{Documenting methods} \texttt{.method} can also include
+a short documentation of the method, after the
+method (or free function) pointer.
+
+<<lang=cpp>>=
+    .method( "stats", &Bar::stats,
+        "vector indicating the number of times x has been read and written" )
+@
+
+TODO: mention overloading, need good example.
+
+
+\paragraph{Const and non-const member functions}
+
+\texttt{method} is able to expose both \texttt{const} and \texttt{non const}
+member functions of a class. There are however situations where
+a class defines two versions of the same method, differing only in their
+signature by the \texttt{const}-ness. It is for example the case of the
+member functions \texttt{back} of the \texttt{std::vector} template from
+the STL.
+
+<<lang=cpp>>=
+reference back ( );
+const_reference back ( ) const;
+@
+
+To resolve the ambiguity, it is possible to use \texttt{const\_method}
+or \texttt{nonconst\_method} instead of \texttt{method} in order
+to restrict the candidate methods.
+
+\paragraph{Special methods}
+
+\pkg{Rcpp} considers the methods \texttt{[[} and \texttt{[[<-} special,
+and promotes them to indexing methods on the \proglang{R} side.
+
+\subsubsection{Object finalizers}
+
+The \texttt{.finalizer} member function of \texttt{class\_} can be used to
+register a finalizer. A finalizer is a free function that takes a pointer
+to the target class and return \texttt{void}. The finalizer is called
+before the destructor and so operates on a valid object of the target class.
+
+It can be used to perform operations, releasing resources, etc ...
+
+The finalizer is called automatically when the \proglang{R} object that encapsulates
+the \proglang{C++} object is garbage collected.
+
+\subsubsection{S4 dispatch}
+
+When a \proglang{C++} class is exposed by the \texttt{class\_} template,
+a new S4 class is registered as well. The name of the S4 class is
+obfuscated in order to avoid name clashes (i.e. two modules exposing the
+same class).
+
+This allows implementation of \proglang{R}-level
+(S4) dispatch. For example, one might implement the \texttt{show}
+method for \proglang{C++} \texttt{World} objects:
+
+<<eval=FALSE>>=
+setMethod( "show", yada$World , function(object) {
+    msg <- paste( "World object with message : ", object$greet() )
+    writeLines( msg )
+} )
+@
+
+TODO: mention R inheritance (John ?)
+
+\subsubsection{Full example}
+
+% TODO: maybe replace this by something from wls or RcppModels ?
+
+The following example illustrates how to use Rcpp modules to expose
+the class \texttt{std::vector<double>} from the STL.
+
+<<lang=cpp>>=
+// convenience typedef
+typedef std::vector<double> vec;
+
+// helpers
+void vec_assign( vec* obj, Rcpp::NumericVector data ) {
+    obj->assign( data.begin(), data.end() );
+}
+
+void vec_insert( vec* obj, int position, Rcpp::NumericVector data) {
+    vec::iterator it = obj->begin() + position;
+    obj->insert( it, data.begin(), data.end() );
+}
+
+Rcpp::NumericVector vec_asR( vec* obj ) {
+    return Rcpp::wrap( *obj );
+}
+
+void vec_set( vec* obj, int i, double value ) {
+    obj->at( i ) = value;
+}
+
+RCPP_MODULE(mod_vec) {
+    using namespace Rcpp;
+
+    // we expose the class std::vector<double> as "vec" on the R side
+    class_<vec>( "vec")
+
+    // exposing constructors
+    .constructor()
+    .constructor<int>()
+
+    // exposing member functions
+    .method( "size", &vec::size)
+    .method( "max_size", &vec::max_size)
+    .method( "resize", &vec::resize)
+    .method( "capacity", &vec::capacity)
+    .method( "empty", &vec::empty)
+    .method( "reserve", &vec::reserve)
+    .method( "push_back", &vec::push_back )
+    .method( "pop_back", &vec::pop_back )
+    .method( "clear", &vec::clear )
+
+    // specifically exposing const member functions
+    .const_method( "back", &vec::back )
+    .const_method( "front", &vec::front )
+    .const_method( "at", &vec::at )
+
+    // exposing free functions taking a std::vector<double>*
+    // as their first argument
+    .method( "assign", &vec_assign )
+    .method( "insert", &vec_insert )
+    .method( "as.vector", &vec_asR )
+
+    // special methods for indexing
+    .const_method( "[[", &vec::at )
+    .method( "[[<-", &vec_set )
+
+    ;
+}
+@
+
+<<echo=FALSE,results=hide>>=
+fx_vec <- cxxfunction(, '', includes = '
+// convenience typedef
+typedef std::vector<double> vec;
+
+// helpers
+void vec_assign( vec* obj, Rcpp::NumericVector data ) {
+    obj->assign( data.begin(), data.end() );
+}
+
+void vec_insert( vec* obj, int position, Rcpp::NumericVector data) {
+    vec::iterator it = obj->begin() + position;
+    obj->insert( it, data.begin(), data.end() );
+}
+
+Rcpp::NumericVector vec_asR( vec* obj ) {
+    return Rcpp::wrap( *obj );
+}
+
+void vec_set( vec* obj, int i, double value ) {
+    obj->at( i ) = value;
+}
+
+RCPP_MODULE(mod_vec) {
+    using namespace Rcpp;
+
+    // we expose the class std::vector<double> as "vec" on the R side
+    class_<vec>( "vec")
+
+    // exposing constructors
+    .constructor()
+    .constructor<int>()
+
+    // exposing member functions
+    .method( "size", &vec::size)
+    .method( "max_size", &vec::max_size)
+    .method( "resize", &vec::resize)
+    .method( "capacity", &vec::capacity)
+    .method( "empty", &vec::empty)
+    .method( "reserve", &vec::reserve)
+    .method( "push_back", &vec::push_back )
+    .method( "pop_back", &vec::pop_back )
+    .method( "clear", &vec::clear )
+
+    // specifically exposing const member functions
+    .const_method( "back", &vec::back )
+    .const_method( "front", &vec::front )
+    .const_method( "at", &vec::at )
+
+    // exposing free functions taking a std::vector<double>*
+    // as their first argument
+    .method( "assign", &vec_assign )
+    .method( "insert", &vec_insert )
+    .method( "as.vector", &vec_asR )
+
+    // special methods for indexing
+    .const_method( "[[", &vec::at )
+    .method( "[[<-", &vec_set )
+
+    ;
+}
+', plugin = "Rcpp" )
+mod_vec <- Module( "mod_vec", getDynLib(fx_vec), mustStart = TRUE )
+@
+
+<<>>=
+vec <- mod_vec$vec
+v <- new( vec )
+v$reserve( 50L )
+v$assign( 1:10 )
+v$push_back( 10 )
+v$size()
+v$capacity()
+v[[ 0L ]]
+v$as.vector()
+@
+
+\section{Using modules in other packages}
+
+\subsection{Namespace import/export}
+
+\subsubsection{Import all functions and classes}
+
+When using \pkg{Rcpp} modules in a packages, the client package needs to
+import \pkg{Rcpp}'s namespace. This is achieved by adding the
+following line to the \texttt{NAMESPACE} file.
+
+<<echo=FALSE,eval=TRUE>>=
+options( prompt = " ", continue = " " )
+@
+
+<<eval=FALSE>>=
+import( Rcpp )
+@
+
+Loading the module must happen after the dynamic library of the
+package is loaded. The most appropriate place for this is
+within the \Sexpr{link(".onLoad" )} hook.
+
+<<eval=FALSE>>=
+# grab the namespace
+NAMESPACE <- environment()
+
+.onLoad <- function(libname, pkgname) {
+    ## load the module and store it in our namespace
+    yada <- Module( "yada" )
+    populate( yada, NAMESPACE  )
+}
+@
+
+The call to \texttt{populate} installs all functions and classes from the
+module into the namespace of package.
+
+<<echo=FALSE,eval=TRUE>>=
+options( prompt = "> ", continue = "+ " )
+@
+
+\subsubsection{Just expose the module}
+
+Alternatively, it is possible to just expose the module to the user of the package,
+and let them extract the functions and classes as needed. This uses lazy loading
+so that the module is only loaded the first time the user attempts to extract
+a function or a class with the dollar extractor.
+
+<<eval=FALSE>>=
+# grab the namespace
+NAMESPACE <- environment()
+
+yada <- Module( "yada" )
+
+.onLoad <- function(libname, pkgname) {
+    # placeholder
+}
+@
+
+
+\subsection{Support for modules in skeleton generator}
+
+The \Sexpr{link("Rcpp.package.skeleton")} function has been improved to help
+\pkg{Rcpp} modules. When the \texttt{module} argument is set to \texttt{TRUE},
+the skeleton generator installs code that uses a simple module.
+
+<<eval=FALSE>>=
+Rcpp.package.skeleton( "testmod", module = TRUE )
+@
+
+\subsection{Module documentation}
+
+\pkg{Rcpp} defines a \Sexpr{link("prompt")} method for the
+\Sexpr{linkS4class("Module")} class, allowing generation of a skeleton of an Rd
+file containing some information about the module.
+
+<<eval=FALSE>>=
+yada <- Module( "yada" )
+prompt( yada, "yada-module.Rd" )
+@
+
+\section{Future extensions}
+
+\texttt{Boost.Python} has many more features that we would like to port
+to Rcpp modules : class inheritance, default arguments, enum
+types, ...
+
+\section{Summary}
+
+This note introduced \textsl{Rcpp modules} and illustrated how to expose
+\proglang{C++} function and classes more easily to \proglang{R}.
+We hope that \proglang{R} and \proglang{C++} programmers
+find \textsl{Rcpp modules} useful.
+
+\bibliographystyle{plainnat}
+\bibliography{Rcpp}
+
 \end{document}
+



More information about the Rcpp-commits mailing list