[Rcpp-commits] r1330 - in pkg/Rcpp/inst/doc: . snippets

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Thu May 27 11:20:24 CEST 2010


Author: romain
Date: 2010-05-27 11:20:24 +0200 (Thu, 27 May 2010)
New Revision: 1330

Added:
   pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
   pkg/Rcpp/inst/doc/snippets/
   pkg/Rcpp/inst/doc/snippets/World.cpp
   pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp
   pkg/Rcpp/inst/doc/snippets/WorldRcppR.R
   pkg/Rcpp/inst/doc/snippets/hello.aux
   pkg/Rcpp/inst/doc/snippets/hello.cpp
   pkg/Rcpp/inst/doc/snippets/helloexpose.aux
   pkg/Rcpp/inst/doc/snippets/helloexpose.cpp
   pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp
   pkg/Rcpp/inst/doc/snippets/highlight.R
   pkg/Rcpp/inst/doc/snippets/highlight.sty
Modified:
   pkg/Rcpp/inst/doc/Makefile
Log:
small Rcpp module vignette

Modified: pkg/Rcpp/inst/doc/Makefile
===================================================================
--- pkg/Rcpp/inst/doc/Makefile	2010-05-27 06:43:49 UTC (rev 1329)
+++ pkg/Rcpp/inst/doc/Makefile	2010-05-27 09:20:24 UTC (rev 1330)
@@ -1,5 +1,5 @@
 
-all: clean index.html Rcpp-unitTests.pdf Rcpp-introduction.pdf
+all: clean index.html Rcpp-unitTests.pdf Rcpp-introduction.pdf Rcpp-modules.pdf
 
 clean:
 	touch Rcpp-unitTests.pdf
@@ -29,3 +29,9 @@
 	Rscript -e "tools::texi2dvi( 'Rcpp-introduction.tex', pdf = TRUE, clean = TRUE )"
 	rm -fr Rcpp-introduction.tex
 
+Rcpp-modules.pdf: snippets Rcpp-modules.Rnw 
+	( cd snippets ; Rscript highlight.R ; cd .. )
+	R CMD Sweave Rcpp-modules.Rnw
+	Rscript -e "tools::texi2dvi( 'Rcpp-modules.tex', pdf = TRUE, clean = TRUE )"
+	rm -fr Rcpp-modules.tex
+

Added: pkg/Rcpp/inst/doc/Rcpp-modules.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-modules.Rnw	                        (rev 0)
+++ pkg/Rcpp/inst/doc/Rcpp-modules.Rnw	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,223 @@
+\documentclass[10pt]{article}
+%\VignetteIndexEntry{Rcpp-modules}
+\usepackage{vmargin}
+\usepackage{color}           
+\usepackage{alltt}           
+
+\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}
+\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}
+  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. \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 were limited to a function by function basis. The 
+programmer would 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: 
+
+\input{snippets/hello}
+
+One can expose a such a function using \texttt{Rcpp} converters
+
+\input{snippets/helloexpose}
+
+Or more traditionally using the R API :
+
+\input{snippets/helloexposerapi}
+
+Either way requires implication from the programmer and quickly becomes an 
+time sink when many functions are involved. \textsl{Rcpp modules} provides a
+much nicer 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: 
+
+\input{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 
+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 : 
+
+\input{snippets/WorldRcpp}
+
+which can be used from R with some S4 glue code: 
+
+\input{snippets/WorldRcppR}
+
+\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 :
+
+\input{snippets/helloModule}
+
+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}:
+
+\input{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 : 
+
+\input{snippets/functions}
+
+can be exposed with the following minimal code: 
+
+\input{snippets/functionsModule}
+
+and used from R: 
+
+\input{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 c++ classes}
+
+Rcpp modules also provide a mechanism for exposing c++ classes. The mechanism 
+internally uses external pointers, but the user should consider this implementation
+details. 
+
+A class is exposed using the \texttt{class\_} class. The \texttt{World}
+class may be exposed to R :
+
+\input{snippets/WorldModule}
+
+\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. 
+
+The construction of the object is then followed by two calls to the 
+\texttt{method} member function of \texttt{class\_<World>}. Each call simply 
+register a member function by providing the name to use on the R 
+side (e.g. "greet") and the reference to the member function. 
+
+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. 
+
+\input{snippets/WorldModuleR}
+
+\section{Future extensions}
+
+\texttt{Boost.Python} has many more features that we would like to port 
+to Rcpp modules : class inheritance, overloading, default arguments, ... 
+
+
+\end{document}
+

Added: pkg/Rcpp/inst/doc/snippets/World.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/World.cpp	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/World.cpp	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,10 @@
+class World {
+public:
+    World() : msg("hello"){}
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+
+private:
+    std::string msg;
+};
+

Added: pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/WorldRcpp.cpp	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,19 @@
+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 ;
+}

Added: pkg/Rcpp/inst/doc/snippets/WorldRcppR.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/WorldRcppR.R	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/WorldRcppR.R	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,14 @@
+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()
+

Added: pkg/Rcpp/inst/doc/snippets/hello.aux
===================================================================
--- pkg/Rcpp/inst/doc/snippets/hello.aux	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/hello.aux	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,23 @@
+\relax 
+\@setckpt{snippets/hello}{
+\setcounter{page}{3}
+\setcounter{equation}{0}
+\setcounter{enumi}{0}
+\setcounter{enumii}{0}
+\setcounter{enumiii}{0}
+\setcounter{enumiv}{0}
+\setcounter{footnote}{0}
+\setcounter{mpfootnote}{0}
+\setcounter{part}{0}
+\setcounter{section}{1}
+\setcounter{subsection}{0}
+\setcounter{subsubsection}{0}
+\setcounter{paragraph}{0}
+\setcounter{subparagraph}{0}
+\setcounter{figure}{0}
+\setcounter{table}{0}
+\setcounter{Item}{0}
+\setcounter{Hfootnote}{0}
+\setcounter{FancyVerbLine}{0}
+\setcounter{section at level}{1}
+}

Added: pkg/Rcpp/inst/doc/snippets/hello.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/hello.cpp	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/hello.cpp	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,5 @@
+const char* hello( std::string who ){
+	std::string result( "hello " ) ;
+	result += who ; 
+	return result.c_str() ;
+}

Added: pkg/Rcpp/inst/doc/snippets/helloexpose.aux
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloexpose.aux	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/helloexpose.aux	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,23 @@
+\relax 
+\@setckpt{snippets/helloexpose}{
+\setcounter{page}{5}
+\setcounter{equation}{0}
+\setcounter{enumi}{0}
+\setcounter{enumii}{0}
+\setcounter{enumiii}{0}
+\setcounter{enumiv}{0}
+\setcounter{footnote}{0}
+\setcounter{mpfootnote}{0}
+\setcounter{part}{0}
+\setcounter{section}{1}
+\setcounter{subsection}{0}
+\setcounter{subsubsection}{0}
+\setcounter{paragraph}{0}
+\setcounter{subparagraph}{0}
+\setcounter{figure}{0}
+\setcounter{table}{0}
+\setcounter{Item}{0}
+\setcounter{Hfootnote}{0}
+\setcounter{FancyVerbLine}{0}
+\setcounter{section at level}{1}
+}

Added: pkg/Rcpp/inst/doc/snippets/helloexpose.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloexpose.cpp	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/helloexpose.cpp	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,5 @@
+RcppExport SEXP hello_wrapper( SEXP who){
+    std::string input = Rcpp::as<std::string>( who )
+    const char* result = hello( input ) ;
+    return Rcpp::wrap( result );
+}

Added: pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp
===================================================================
--- pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/helloexposerapi.cpp	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,5 @@
+extern "C" SEXP hello_wrapper( SEXP who){
+    std::string input = CHAR(STRING_ELT(input,0)) ;
+    const char* result = hello( input ) ;
+    return mkString( result );
+}

Added: pkg/Rcpp/inst/doc/snippets/highlight.R
===================================================================
--- pkg/Rcpp/inst/doc/snippets/highlight.R	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/highlight.R	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,34 @@
+#!/usr/bin/Rscript
+
+cppfiles <- list.files( pattern = "[.]cpp$" )
+for( f in cppfiles ){
+	base <- sub( "[.]cpp$", "", f )
+	output <- sprintf( "%s.tex", base )
+	system( sprintf( "highlight --input=%s --output=%s -L --pretty-symbols --replace-tabs=4", f, output ) )
+	
+	tex <- readLines( output )
+	keep <- seq( which( tex == "\\noindent" ), which( tex == "\\normalfont" ) )
+	tex <- c( 
+		"\\vspace{1em}\\noindent\\fbox{\\begin{minipage}{0.9\\textwidth}" , 
+		tex[ keep ],
+		"\\end{minipage}}\\vspace{1em}" )
+	
+	writeLines( tex, output )
+}
+
+require( highlight )
+r <- renderer_latex( doc = FALSE )
+r$header <- function(){
+	"\\vspace{1em}\\noindent\\fbox{\\begin{minipage}{0.9\\textwidth}\n\\ttfamily\\noindent\n\\hlstd{}"
+}
+r$footer <- function(){
+	"\\mbox{}\n\\normalfont\n\\end{minipage}}\\vspace{1em}"
+}
+rfiles <- setdiff( list.files( pattern = "[.]R$" ), "highlight.R" )
+for( f in rfiles ){
+	base <- sub( "[.]R$", "", f )
+	output <- sprintf( "%s.tex", base )
+	
+	highlight( f, renderer = r, output = output )
+}
+

Added: pkg/Rcpp/inst/doc/snippets/highlight.sty
===================================================================
--- pkg/Rcpp/inst/doc/snippets/highlight.sty	                        (rev 0)
+++ pkg/Rcpp/inst/doc/snippets/highlight.sty	2010-05-27 09:20:24 UTC (rev 1330)
@@ -0,0 +1,20 @@
+% Style definition file generated by highlight 2.9, http://www.andre-simon.de/ 
+
+% Highlighting theme definition: 
+
+\newcommand{\hlstd}[1]{\textcolor[rgb]{0,0,0}{#1}}
+\newcommand{\hlnum}[1]{\textcolor[rgb]{0.16,0.16,1}{#1}}
+\newcommand{\hlesc}[1]{\textcolor[rgb]{1,0,1}{#1}}
+\newcommand{\hlstr}[1]{\textcolor[rgb]{1,0,0}{#1}}
+\newcommand{\hldstr}[1]{\textcolor[rgb]{0.51,0.51,0}{#1}}
+\newcommand{\hlslc}[1]{\textcolor[rgb]{0.51,0.51,0.51}{\it{#1}}}
+\newcommand{\hlcom}[1]{\textcolor[rgb]{0.51,0.51,0.51}{\it{#1}}}
+\newcommand{\hldir}[1]{\textcolor[rgb]{0,0.51,0}{#1}}
+\newcommand{\hlsym}[1]{\textcolor[rgb]{0,0,0}{#1}}
+\newcommand{\hlline}[1]{\textcolor[rgb]{0.33,0.33,0.33}{#1}}
+\newcommand{\hlkwa}[1]{\textcolor[rgb]{0,0,0}{\bf{#1}}}
+\newcommand{\hlkwb}[1]{\textcolor[rgb]{0.51,0,0}{#1}}
+\newcommand{\hlkwc}[1]{\textcolor[rgb]{0,0,0}{\bf{#1}}}
+\newcommand{\hlkwd}[1]{\textcolor[rgb]{0,0,0.51}{#1}}
+\definecolor{bgcolor}{rgb}{1,1,1}
+



More information about the Rcpp-commits mailing list