[Rcpp-commits] r1374 - in pkg/Rcpp/inst/doc: . Rcpp-modules snippets
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sun May 30 21:34:56 CEST 2010
Author: romain
Date: 2010-05-30 21:34:55 +0200 (Sun, 30 May 2010)
New Revision: 1374
Added:
pkg/Rcpp/inst/doc/Rcpp-modules/
pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules-fake.Rnw
pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules.Rnw
Removed:
pkg/Rcpp/inst/doc/snippets/S4dispatch.R
pkg/Rcpp/inst/doc/snippets/World.cpp
pkg/Rcpp/inst/doc/snippets/WorldModule.cpp
pkg/Rcpp/inst/doc/snippets/WorldModuleR.R
pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp
pkg/Rcpp/inst/doc/snippets/WorldRcppR.R
pkg/Rcpp/inst/doc/snippets/functions.cpp
pkg/Rcpp/inst/doc/snippets/functionsModule.cpp
pkg/Rcpp/inst/doc/snippets/functionsModuleR.R
pkg/Rcpp/inst/doc/snippets/hello.cpp
pkg/Rcpp/inst/doc/snippets/helloModule.cpp
pkg/Rcpp/inst/doc/snippets/helloModuleR.cpp
pkg/Rcpp/inst/doc/snippets/helloexpose.cpp
pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp
pkg/Rcpp/inst/doc/snippets/highlight.sty
pkg/Rcpp/inst/doc/snippets/modulestdvec.cpp
pkg/Rcpp/inst/doc/snippets/stdvectorback.cpp
Modified:
pkg/Rcpp/inst/doc/Makefile
pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
pkg/Rcpp/inst/doc/snippets/highlight.R
Log:
include the snippets in the document
Modified: pkg/Rcpp/inst/doc/Makefile
===================================================================
--- pkg/Rcpp/inst/doc/Makefile 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/Makefile 2010-05-30 19:34:55 UTC (rev 1374)
@@ -29,9 +29,11 @@
Rscript -e "tools::texi2dvi( 'Rcpp-introduction.tex', pdf = TRUE, clean = TRUE )"
rm -fr Rcpp-introduction.tex
-Rcpp-modules.pdf: snippets Rcpp-modules.Rnw
+Rcpp-modules.pdf: Rcpp-modules/Rcpp-modules.Rnw
+ rm Rcpp-modules.Rnw
+ cp -f Rcpp-modules/Rcpp-modules.Rnw .
( cd snippets ; Rscript highlight.R ; cd .. )
- R CMD Sweave Rcpp-modules.Rnw
+ Rscript -e "require(highlight); driver <- HighlightWeaveLatex(); Sweave( 'Rcpp-modules.Rnw', driver = driver ); "
Rscript -e "tools::texi2dvi( 'Rcpp-modules.tex', pdf = TRUE, clean = FALSE )"
bibtex Rcpp-modules
Rscript -e "tools::texi2dvi( 'Rcpp-modules.tex', pdf = TRUE, clean = TRUE )"
@@ -42,3 +44,5 @@
rm -fr Rcpp-modules.aux
rm -fr Rcpp-modules.out
rm -fr Rcpp-modules.log
+ rm Rcpp-modules.Rnw
+ cp Rcpp-modules/Rcpp-modules-fake.Rnw Rcpp-modules.Rnw
Added: pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules-fake.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules-fake.Rnw (rev 0)
+++ pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules-fake.Rnw 2010-05-30 19:34:55 UTC (rev 1374)
@@ -0,0 +1,4 @@
+\documentclass[10pt]{article}
+%\VignetteIndexEntry{Rcpp-modules}
+\begin{document}
+\end{document}
Added: pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules.Rnw (rev 0)
+++ pkg/Rcpp/inst/doc/Rcpp-modules/Rcpp-modules.Rnw 2010-05-30 19:34:55 UTC (rev 1374)
@@ -0,0 +1,445 @@
+\documentclass[10pt]{article}
+%\VignetteIndexEntry{Rcpp-modules}
+\usepackage{vmargin}
+\usepackage{color}
+\usepackage{alltt}
+\usepackage[authoryear,round,longnamesfirst]{natbib}
+
+\setmargrb{0.75in}{0.75in}{0.75in}{0.75in}
+
+\usepackage[colorlinks]{hyperref}
+\author{Dirk Eddelbuettel \and Romain Fran\c{c}ois}
+\title{Exposing C++ functions and classes with Rcpp modules}
+
+
+\begin{document}
+\maketitle
+
+\abstract{
+ \noindent
+ \textsl{Rcpp modules} have been introduced in version 0.8.1 of \texttt{Rcpp}
+ to allow programmers to simply expose C++ functions and classes to R.
+ \textsl{Rcpp modules} are inspired from the \texttt{Boost.Python} \citep{Boost:Python}
+ C++ library which provides the same features (and much more) for
+ Python. This document is a short overview of the capabilities of modules.
+}
+
+\section{Motivation}
+
+Exposing C++ functionality to R is greatly facilitated by the \texttt{Rcpp}
+package and underlying C++ library \citep{CRAN:Rcpp}. \texttt{Rcpp}
+facilitates R and C++ integration by replacing use of the traditionnal R API
+by a consistent set of C++ classes.
+
+However, these facilities are limited to a function by function basis. The
+programmer has to implement a \texttt{.Call} compatible function
+using classes of the \texttt{Rcpp} API.
+
+\subsection{Exposing functions}
+
+Exposing existing C++ functions to R through \texttt{Rcpp}
+usually involves writing an additional wrapper function that is responsible
+for converting input objects to the appropriate types, calling the function
+and converting the results back to a suitable type that can be returned to
+R: the traditionnal \texttt{SEXP} from the R API or any type from the
+\texttt{Rcpp} API that offer implicit conversion to \texttt{SEXP} (many of them do).
+
+Consider the \texttt{hello} function below:
+
+<<lang=cpp>>=
+const char* hello( std::string who ){
+ std::string result( "hello " ) ;
+ result += who ;
+ return result.c_str() ;
+}
+@
+
+One can expose a such a function using \texttt{Rcpp} converters
+
+<<lang=cpp>>=
+RcppExport SEXP hello_wrapper( SEXP who){
+ std::string input = Rcpp::as<std::string>( who )
+ const char* result = hello( input ) ;
+ return Rcpp::wrap( result );
+}
+@
+
+Or more traditionally using the R API :
+
+<<lang=cpp>>=
+extern "C" SEXP hello_wrapper( SEXP who){
+ std::string input = CHAR(STRING_ELT(input,0)) ;
+ const char* result = hello( input ) ;
+ return mkString( result );
+}
+@
+
+Either way requires direct involvement from the programmer and quickly
+becomes an time sink when many functions are involved. \textsl{Rcpp modules}
+provides a much more efficient way to expose the \texttt{hello} function to R.
+
+\subsection{Exposing classes}
+
+Exposing C++ classes or structs is even more of a challenge because it
+requires writing glue code for each function that is to be exposed. Consider the
+simple \texttt{World} class below:
+
+<<lang=cpp>>=
+class World {
+public:
+ World() : msg("hello"){}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+
+private:
+ std::string msg;
+};
+@
+
+We might want a way to create objects of this class, and use the member
+functions \texttt{greet} and \texttt{set} to alter the object. External pointers
+\citep{R:exts} are the perfect vessel for this, and using the
+\texttt{Rcpp:::XPtr} template from \texttt{Rcpp} we can expose the class
+by exposing three functions :
+
+<<lang=cpp>>=
+using namespace Rcpp ;
+
+/** create an external pointer to a World object */
+RcppExport SEXP World__new(){
+ return Rcpp::XPtr<World>( new World, true ) ;
+}
+
+/** invoke the greet method */
+RcppExport SEXP World__greet( SEXP xp ) {
+ Rcpp::XPtr<World> w(xp) ;
+ return Rcpp::wrap( w->greet() ) ;
+}
+
+/** invoke the set method */
+RcppExport SEXP World__set( SEXP xp, SEXP msg ){
+ Rcpp::XPtr<World> w(xp) ;
+ w->set( Rcpp::as<std::string>( msg ) ) ;
+ return R_NilValue ;
+}
+@
+
+which can be used from R with some S4 glue code:
+
+<<eval=FALSE>>=
+setClass( "World", representation( pointer = "externalptr" ) )
+
+World_method <- function(name){
+ paste( "World", name, sep = "__" )
+}
+
+setMethod( "$", "World", function(x, name ){
+ function(...) .Call( World_method(name) , x at pointer, ... )
+} )
+
+w <- new( "World", .Call( World_method( "new" ) ) )
+w$set( "hello world" )
+w$greet()
+@
+
+\texttt{Rcpp} considerably simplifies the code that would be involved for using
+external pointers with the traditional R API. This still involves
+a lot of pattern code that quickly becomes hard to maintain and error prone.
+\textsl{Rcpp modules} offer a much nicer way to expose the \texttt{World}
+class in a way that makes both the internal C++ code and the R code easier.
+
+\section{Rcpp modules}
+
+Rcpp modules are inspired from Python modules that are generated
+by the \texttt{Boost.Python} library. They provide an easy way to expose
+C++ functions and classes to R, grouped together in a single entity.
+
+The module is created in a cpp file using the \texttt{RCPP\_MODULE}
+macro, which then contains declarative code of what the module
+exposes to R.
+
+\subsection{Exposing C++ functions}
+
+Consider the \texttt{hello} function from the previous section.
+We can expose it to R :
+
+<<lang=cpp>>=
+const char* hello( std::string who ){
+ std::string result( "hello " ) ;
+ result += who ;
+ return result.c_str() ;
+}
+
+RCPP_MODULE(yada){
+ using namespace Rcpp ;
+ function( "hello", &hello ) ;
+}
+@
+
+The code creates a module called an Rcpp module called \texttt{yada}
+that exposes the \texttt{hello} function. \texttt{Rcpp} automatically
+deduces the conversions that are needed for input and output.
+
+On the R side, the module is simply retrieved by using the \texttt{Module}
+function from \texttt{Rcpp}:
+
+<<eval=FALSE>>=
+require( Rcpp )
+yada <- Module( "yada" )
+yada$hello( "world" )
+@
+
+A module can contain any number of calls to \texttt{function} to register
+many internal functions to 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 ) ;
+}
+@
+
+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 used from 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 on the functions to be exposed are:
+\begin{itemize}
+\item It takes between 0 and 65 parameters.
+\item The type of each input parameter must be manageable by the \texttt{Rcpp::as}
+template.
+\item The output type must be either \texttt{void} or any type that
+can be managed by the \texttt{Rcpp::wrap} template
+\end{itemize}
+
+\subsection{Exposing C++ classes}
+
+Rcpp modules also provide a mechanism for exposing C++ classes. The mechanism
+internally uses external pointers, but the user should consider this as
+hidden implementation details as this is properly encapsulated.
+
+A class is exposed using the \texttt{class\_} class. The \texttt{World}
+class may be exposed to R :
+
+<<lang=cpp>>=
+class World {
+public:
+ World() : msg("hello"){}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+
+private:
+ std::string msg;
+};
+
+void clearWorld( World* w){
+ w->set( "" ) ;
+}
+
+RCPP_MODULE(yada){
+ using namespace Rcpp ;
+
+ class_<World>( "World" )
+ .method( "greet", &World::greet )
+ .method( "set", &World::set )
+ .method( "clear", &clearWorld )
+ ;
+
+}
+@
+
+\texttt{class\_} is templated by the C++ class or struct that is to be exposed
+to R. The parameter of the \texttt{class\_<World>} constructor is the name we will
+use on the R side. It usually makes sense to use the same name as the class
+name, but this is not forced, which might be useful when exposing a class
+generated from a template.
+
+The construction of the object is then followed by two calls to the
+\texttt{method} member function of \texttt{class\_<World>}. \texttt{method}
+can expose :
+\begin{itemize}
+\item member functions of the target class, such as \texttt{greet} or \texttt{set}, by
+providing the name that will be used on the R side (e.g. \texttt{greet}) and
+a pointer to the actual member function (e.g. \texttt{\&World::greet} )
+\item free funtions that take a pointer to the target class as their
+first parameter such as the C++ function \texttt{clearWorld} in the previous
+example. Again, we provide the R name for the method (\texttt{clear}) and
+a pointer to the C++ function.
+\end{itemize}
+
+The module exposes the default constructor of the \texttt{World} class as well
+to support creation of \texttt{World} objects from R. The Rcpp module assumes
+responsabilities for type conversion for input and output types.
+
+<<eval=FALSE>>=
+require( Rcpp )
+
+# load the module
+yada <- Module( "yada" )
+
+# grab the World class
+World <- yada$World
+
+# create a new World object
+w <- new( World )
+
+# use methods of the class
+w$greet()
+w$set( "hello world" )
+w$greet()
+w$clear()
+w$greet()
+@
+
+\subsubsection{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;
+@
+
+\subsubsection{S4 dispatch}
+
+When a C++ class is exposed by the \texttt{class\_} template,
+a new S4 class is registered as well. This allows implementation of R-level
+(S4) dispatch. For example, one might implement the \texttt{show}
+method for C++ \texttt{World} objects:
+
+<<eval=FALSE>>=
+setMethod( "show", "World", function(object){
+ msg <- paste( "World object with message : ", object$greet() )
+ writeLines( msg )
+} )
+@
+
+\subsubsection{Special methods}
+
+\texttt{Rcpp} considers the methods \texttt{[[} and \texttt{[[<-} special,
+and promote them to indexing methods on the R side.
+
+\subsubsection{Full example}
+
+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(yada){
+ using namespace Rcpp ;
+
+ // we expose the class std::vector<double> as "vec" on the R side
+ class_<vec>( "vec")
+
+ // 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 )
+
+ ;
+}
+@
+
+\section{Future extensions}
+
+\texttt{Boost.Python} has many more features that we would like to port
+to Rcpp modules : class inheritance, overloading, default arguments, ...
+
+\section{References}
+
+\bibliographystyle{abbrvnat}
+\bibliography{Rcpp-modules}
+
+\end{document}
+
Modified: pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-modules.Rnw 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/Rcpp-modules.Rnw 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,270 +1,4 @@
\documentclass[10pt]{article}
%\VignetteIndexEntry{Rcpp-modules}
-\usepackage{vmargin}
-\usepackage{color}
-\usepackage{alltt}
-\usepackage[authoryear,round,longnamesfirst]{natbib}
-
-\setmargrb{0.75in}{0.75in}{0.75in}{0.75in}
-
-% from highlight
-\input{snippets/highlight.sty}
-\newsavebox{\hlboxopenbrace}
-\newsavebox{\hlboxclosebrace}
-\newsavebox{\hlboxlessthan}
-\newsavebox{\hlboxgreaterthan}
-\newsavebox{\hlboxdollar}
-\newsavebox{\hlboxunderscore}
-\newsavebox{\hlboxand}
-\newsavebox{\hlboxhash}
-\newsavebox{\hlboxat}
-\newsavebox{\hlboxbackslash}
-\newsavebox{\hlboxpercent}
-\newsavebox{\hlboxhat}
-
-\setbox\hlboxopenbrace=\hbox{\verb.{.}
-\setbox\hlboxclosebrace=\hbox{\verb.}.}
-\setbox\hlboxlessthan=\hbox{\verb.<.}
-\setbox\hlboxgreaterthan=\hbox{\verb.>.}
-\setbox\hlboxdollar=\hbox{\verb.$.}
-\setbox\hlboxunderscore=\hbox{\verb._.}
-\setbox\hlboxand=\hbox{\verb.&.}
-\setbox\hlboxhash=\hbox{\verb.#.}
-\setbox\hlboxat=\hbox{\verb. at .}
-\setbox\hlboxbackslash=\hbox{\verb.\.}
-\setbox\hlboxpercent=\hbox{\verb.\%.}
-\setbox\hlboxhat=\hbox{\verb.^.}
-\def\urltilda{\kern -.15em\lower .7ex\hbox{\~{}}\kern .04em}
-
-% from R package "highlight"
-\newsavebox{\hlboxsinglequote}
-\setbox\hlboxsinglequote=\hbox{\verb.'.}
-
-\newcommand{\hlnumber}[1]{\textcolor[rgb]{0.0823529411764706,0.0784313725490196,0.709803921568627}{#1}}%
-\newcommand{\hlfunctioncall}[1]{\textcolor[rgb]{1,0,0}{#1}}%
-\newcommand{\hlstring}[1]{\textcolor[rgb]{0.6,0.6,1}{#1}}%
-\newcommand{\hlkeyword}[1]{\textcolor[rgb]{0,0,0}{\textbf{#1}}}%
-\newcommand{\hlargument}[1]{\textcolor[rgb]{0.694117647058824,0.247058823529412,0.0196078431372549}{#1}}%
-\newcommand{\hlcomment}[1]{\textcolor[rgb]{0.8,0.8,0.8}{#1}}%
-\newcommand{\hlroxygencomment}[1]{\textcolor[rgb]{0,0.592156862745098,1}{#1}}%
-\newcommand{\hlformalargs}[1]{\textcolor[rgb]{0.0705882352941176,0.713725490196078,0.0705882352941176}{#1}}%
-\newcommand{\hleqformalargs}[1]{\textcolor[rgb]{0.0705882352941176,0.713725490196078,0.0705882352941176}{#1}}%
-\newcommand{\hlassignement}[1]{\textcolor[rgb]{0.215686274509804,0.215686274509804,0.384313725490196}{\textbf{#1}}}%
-\newcommand{\hlpackage}[1]{\textcolor[rgb]{0.588235294117647,0.713725490196078,0.145098039215686}{#1}}%
-\newcommand{\hlslot}[1]{\textit{#1}}%
-\newcommand{\hlsymbol}[1]{\textcolor[rgb]{0,0,0}{#1}}%
-\newcommand{\hlprompt}[1]{\textcolor[rgb]{0,0,0}{#1}}%
-
-\usepackage[colorlinks]{hyperref}
-
-\newcommand{\proglang}[1]{\textsf{#1}}
-\newcommand{\pkg}[1]{{\fontseries{b}\selectfont #1}}
-
-\author{Dirk Eddelbuettel \and Romain Fran\c{c}ois}
-\title{Exposing \proglang{C++} functions and classes with \pkg{Rcpp} modules}
-
-
\begin{document}
-\maketitle
-
-\abstract{
- \noindent
- \textsl{Rcpp modules} have been introduced in version 0.8.1 of \pkg{Rcpp}
- to allow programmers to simply expose \proglang{C++} functions and classes to R.
- \textsl{Rcpp modules} are inspired from the \texttt{Boost.Python} \citep{Boost:Python}
- \proglang{C++} library which provides the same features (and much more) for
- Python. This document is a short overview of the capabilities of modules.
-}
-
-\section{Motivation}
-
-Exposing \proglang{C++} functionality to R is greatly facilitated by the \pkg{Rcpp}
-package and underlying \proglang{C++} library \citep{CRAN:Rcpp}. \pkg{Rcpp}
-facilitates R and \proglang{C++} integration by replacing use of the traditionnal R API
-by a consistent set of \proglang{C++} classes.
-
-However, these facilities are limited to a function by function basis. The
-programmer has to implement a \texttt{.Call} compatible function
-using classes of the \pkg{Rcpp} API.
-
-\subsection{Exposing functions}
-
-Exposing existing \proglang{C++} functions to R through \pkg{Rcpp}
-usually involves writing an additional wrapper function that is responsible
-for converting input objects to the appropriate types, calling the function
-and converting the results back to a suitable type that can be returned to
-R: the traditionnal \texttt{SEXP} from the R API or any type from the
-\pkg{Rcpp} API that offer implicit conversion to \texttt{SEXP} (many of them do).
-
-Consider the \texttt{hello} function below:
-
-\InputIfFileExists{snippets/hello}{}{}
-
-One can expose a such a function using \pkg{Rcpp} converters
-
-\InputIfFileExists{snippets/helloexpose}{}{}
-
-Or more traditionally using the R API :
-
-\InputIfFileExists{snippets/helloexposerapi}{}{}
-
-Either way requires direct involvement from the programmer and quickly
-becomes an time sink when many functions are involved. \textsl{Rcpp modules}
-provides a much more efficient way to expose the \texttt{hello} function to R.
-
-\subsection{Exposing classes}
-
-Exposing \proglang{C++} classes or structs is even more of a challenge because it
-requires writing glue code for each function that is to be exposed. Consider the
-simple \texttt{World} class below:
-
-\InputIfFileExists{snippets/World}{}{}
-
-We might want a way to create objects of this class, and use the member
-functions \texttt{greet} and \texttt{set} to alter the object. External pointers
-\citep{R:exts} are the perfect vessel for this, and using the
-\texttt{Rcpp:::XPtr} template from \pkg{Rcpp} we can expose the class
-by exposing three functions :
-
-\InputIfFileExists{snippets/WorldRcpp}{}{}
-
-which can be used from R with some S4 glue code:
-
-\InputIfFileExists{snippets/WorldRcppR}{}{}
-
-\pkg{Rcpp} considerably simplifies the code that would be involved for using
-external pointers with the traditional R API. This still involves
-a lot of pattern code that quickly becomes hard to maintain and error prone.
-\textsl{Rcpp modules} offer a much nicer way to expose the \texttt{World}
-class in a way that makes both the internal \proglang{C++} code and the R code easier.
-
-\section{\pkg{Rcpp} modules}
-
-\textsl{Rcpp modules} are inspired from Python modules that are generated
-by the \texttt{Boost.Python} library. They provide an easy way to expose
-\proglang{C++} functions and classes to R, grouped together in a single entity.
-
-The module is created in a cpp file using the \texttt{RCPP\_MODULE}
-macro, which then contains declarative code of what the module
-exposes to R.
-
-\subsection{Exposing \proglang{C++} functions}
-
-Consider the \texttt{hello} function from the previous section.
-We can expose it to R :
-
-\InputIfFileExists{snippets/helloModule}{}{}
-
-The code creates a module called an \pkg{Rcpp} module called \texttt{yada}
-that exposes the \texttt{hello} function. \pkg{Rcpp} automatically
-deduces the conversions that are needed for input and output.
-
-On the R side, the module is simply retrieved by using the \texttt{Module}
-function from \pkg{Rcpp}:
-
-\InputIfFileExists{snippets/helloModuleR}{}{}
-
-A module can contain any number of calls to \texttt{function} to register
-many internal functions to R. For example, these 6 functions :
-
-\InputIfFileExists{snippets/functions}{}{}
-
-can be exposed with the following minimal code:
-
-\InputIfFileExists{snippets/functionsModule}{}{}
-
-and used from R:
-
-\InputIfFileExists{snippets/functionsModuleR}{}{}
-
-The requirements on the functions to be exposed are:
-\begin{itemize}
-\item It takes between 0 and 65 parameters.
-\item The type of each input parameter must be manageable by the \texttt{Rcpp::as}
-template.
-\item The output type must be either \texttt{void} or any type that
-can be managed by the \texttt{Rcpp::wrap} template
-\end{itemize}
-
-\subsection{Exposing \proglang{C++} classes}
-
-\pkg{Rcpp} modules also provide a mechanism for exposing \proglang{C++} classes. The mechanism
-internally uses external pointers, but the user should consider this as
-hidden implementation details as this is properly encapsulated.
-
-A class is exposed using the \texttt{class\_} class. The \texttt{World}
-class may be exposed to R :
-
-\InputIfFileExists{snippets/WorldModule}{}{}
-
-\texttt{class\_} is templated by the \proglang{C++} class or struct that is to be exposed
-to R. The parameter of the \texttt{class\_<World>} constructor is the name we will
-use on the R side. It usually makes sense to use the same name as the class
-name, but this is not forced, which might be useful when exposing a class
-generated from a template.
-
-The construction of the object is then followed by two calls to the
-\texttt{method} member function of \texttt{class\_<World>}. \texttt{method}
-can expose :
-\begin{itemize}
-\item member functions of the target class, such as \texttt{greet} or \texttt{set}, by
-providing the name that will be used on the R side (e.g. \texttt{greet}) and
-a pointer to the actual member function (e.g. \texttt{\&World::greet} )
-\item free funtions that take a pointer to the target class as their
-first parameter such as the \proglang{C++} function \texttt{clearWorld} in the previous
-example. Again, we provide the R name for the method (\texttt{clear}) and
-a pointer to the \proglang{C++} function.
-\end{itemize}
-
-The module exposes the default constructor of the \texttt{World} class as well
-to support creation of \texttt{World} objects from R. The \pkg{Rcpp} module assumes
-responsabilities for type conversion for input and output types.
-
-\InputIfFileExists{snippets/WorldModuleR}{}{}
-
-\subsubsection{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.
-
-\InputIfFileExists{snippets/stdvectorback}{}{}
-
-\subsubsection{S4 dispatch}
-
-When a \proglang{C++} class is exposed by the \texttt{class\_} template,
-a new S4 class is registered as well. This allows implementation of R-level
-(S4) dispatch. For example, one might implement the \texttt{show}
-method for \proglang{C++} \texttt{World} objects:
-
-\InputIfFileExists{snippets/S4dispatch}{}{}
-
-\subsubsection{Special methods}
-
-\pkg{Rcpp} considers the methods \texttt{[[} and \texttt{[[<-} special,
-and promote them to indexing methods on the R side.
-
-\subsubsection{Full example}
-
-The following example illustrates how to use \pkg{Rcpp} modules to expose
-the class \texttt{std::vector<double>} from the STL.
-
-\InputIfFileExists{snippets/modulestdvec}{}{}
-
-
-
-\section{Future extensions}
-
-\texttt{Boost.Python} has many more features that we would like to port
-to Rcpp modules : class inheritance, overloading, default arguments, ...
-
-\section{References}
-
-\bibliographystyle{abbrvnat}
-\bibliography{Rcpp-modules}
-
\end{document}
-
Deleted: pkg/Rcpp/inst/doc/snippets/S4dispatch.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/S4dispatch.R 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/S4dispatch.R 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,4 +0,0 @@
-setMethod( "show", "World", function(object){
- msg <- paste( "World object with message : ", object$greet() )
- writeLines( msg )
-} )
Deleted: pkg/Rcpp/inst/doc/snippets/World.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/World.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/World.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,10 +0,0 @@
-class World {
-public:
- World() : msg("hello"){}
- void set(std::string msg) { this->msg = msg; }
- std::string greet() { return msg; }
-
-private:
- std::string msg;
-};
-
Deleted: pkg/Rcpp/inst/doc/snippets/WorldModule.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldModule.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/WorldModule.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,25 +0,0 @@
-class World {
-public:
- World() : msg("hello"){}
- void set(std::string msg) { this->msg = msg; }
- std::string greet() { return msg; }
-
-private:
- std::string msg;
-};
-
-void clearWorld( World* w){
- w->set( "" ) ;
-}
-
-RCPP_MODULE(yada){
- using namespace Rcpp ;
-
- class_<World>( "World" )
- .method( "greet", &World::greet )
- .method( "set", &World::set )
- .method( "clear", &clearWorld )
- ;
-
-}
-
Deleted: pkg/Rcpp/inst/doc/snippets/WorldModuleR.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldModuleR.R 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/WorldModuleR.R 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,18 +0,0 @@
-require( Rcpp )
-
-# load the module
-yada <- Module( "yada" )
-
-# grab the World class
-World <- yada$World
-
-# create a new World object
-w <- new( World )
-
-# use methods of the class
-w$greet()
-w$set( "hello world" )
-w$greet()
-w$clear()
-w$greet()
-
Deleted: pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,19 +0,0 @@
-using namespace Rcpp ;
-
-/** create an external pointer to a World object */
-RcppExport SEXP World__new(){
- return Rcpp::XPtr<World>( new World, true ) ;
-}
-
-/** invoke the greet method */
-RcppExport SEXP World__greet( SEXP xp ) {
- Rcpp::XPtr<World> w(xp) ;
- return Rcpp::wrap( w->greet() ) ;
-}
-
-/** invoke the set method */
-RcppExport SEXP World__set( SEXP xp, SEXP msg ){
- Rcpp::XPtr<World> w(xp) ;
- w->set( Rcpp::as<std::string>( msg ) ) ;
- return R_NilValue ;
-}
Deleted: pkg/Rcpp/inst/doc/snippets/WorldRcppR.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldRcppR.R 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/WorldRcppR.R 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,14 +0,0 @@
-setClass( "World", representation( pointer = "externalptr" ) )
-
-World_method <- function(name){
- paste( "World", name, sep = "__" )
-}
-
-setMethod( "$", "World", function(x, name ){
- function(...) .Call( World_method(name) , x at pointer, ... )
-} )
-
-w <- new( "World", .Call( World_method( "new" ) ) )
-w$set( "hello world" )
-w$greet()
-
Deleted: pkg/Rcpp/inst/doc/snippets/functions.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/functions.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/functions.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,24 +0,0 @@
-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 ) ;
-}
-
Deleted: pkg/Rcpp/inst/doc/snippets/functionsModule.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/functionsModule.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/functionsModule.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,11 +0,0 @@
-RCPP_MODULE(yada){
- using namespace Rcpp ;
-
- function( "hello" , &hello ) ;
- function( "bar" , &bar ) ;
- function( "foo" , &foo ) ;
- function( "bla" , &bla ) ;
- function( "bla1" , &bla1 ) ;
- function( "bla2" , &bla2 ) ;
-}
-
Deleted: pkg/Rcpp/inst/doc/snippets/functionsModuleR.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/functionsModuleR.R 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/functionsModuleR.R 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,10 +0,0 @@
-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 )
-
Deleted: pkg/Rcpp/inst/doc/snippets/hello.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/hello.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/hello.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,5 +0,0 @@
-const char* hello( std::string who ){
- std::string result( "hello " ) ;
- result += who ;
- return result.c_str() ;
-}
Deleted: pkg/Rcpp/inst/doc/snippets/helloModule.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloModule.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/helloModule.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,12 +0,0 @@
-
-const char* hello( std::string who ){
- std::string result( "hello " ) ;
- result += who ;
- return result.c_str() ;
-}
-
-RCPP_MODULE(yada){
- using namespace Rcpp ;
- function( "hello", &hello ) ;
-}
-
Deleted: pkg/Rcpp/inst/doc/snippets/helloModuleR.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloModuleR.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/helloModuleR.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,3 +0,0 @@
-require( Rcpp )
-yada <- Module( "yada" )
-yada$hello( "world" )
Deleted: pkg/Rcpp/inst/doc/snippets/helloexpose.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloexpose.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/helloexpose.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,5 +0,0 @@
-RcppExport SEXP hello_wrapper( SEXP who){
- std::string input = Rcpp::as<std::string>( who )
- const char* result = hello( input ) ;
- return Rcpp::wrap( result );
-}
Deleted: pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp 2010-05-30 19:34:55 UTC (rev 1374)
@@ -1,5 +0,0 @@
-extern "C" SEXP hello_wrapper( SEXP who){
- std::string input = CHAR(STRING_ELT(input,0)) ;
- const char* result = hello( input ) ;
- return mkString( result );
-}
Modified: pkg/Rcpp/inst/doc/snippets/highlight.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/highlight.R 2010-05-30 07:26:34 UTC (rev 1373)
+++ pkg/Rcpp/inst/doc/snippets/highlight.R 2010-05-30 19:34:55 UTC (rev 1374)
@@ -17,9 +17,9 @@
}
require( highlight )
-if( compareVersion( "0.1-9", packageDescription( "highlight" )[["Version"]] ) ){
- stop( "version 0.1-9 of highlight is required for the minipage argument" )
-}
[TRUNCATED]
To get the complete diff run:
svnlook diff /svnroot/rcpp -r 1374
More information about the Rcpp-commits
mailing list