[Rcpp-devel] any preprocessor expert around ?
Romain Francois
romain at r-enthusiasts.com
Fri Apr 23 10:27:15 CEST 2010
Hello,
In the svn version of Rcpp (to be released soon) I have added some
macros to facilitate writing functions in Rcpp.
The macros are RCPP_FUNCTION_0, RCPP_FUNCTION_1, ..., RCPP_FUNCTION_65
(65 is the maximum number of arguments in a .Call call).
It goes like this :
RCPP_FUNCTION_3(int,foobar,
int x, int y, NumericVector z){
return x + y + z.size() ;
}
- The first argument of the macro is the type that is returned by the
function body. This can be whatever Rcpp::wrap can handle, so int,
double, Rcpp classes, STL classes, ...)
- The second argument is the name of the function
- The other arguments (3 arguments in this case because we use
RCPP_FUNCTION_3) are arguments of the function. These can be anything
that Rcpp::as can handle, so again any primitive type, SEXP, any Rcpp
(new api) class, some STL classes, ...
Internally the macro expands to (slightly reformatted for the email):
int foobar__rcpp__wrapper__(int x, int y, NumericVector z) ;
extern "C" SEXP foobar(SEXP x0, SEXP x1, SEXP x2){
SEXP res = R_NilValue ;
try{
res = ::Rcpp::wrap( foobar__rcpp__wrapper__(
::Rcpp::internal::converter( x0 ),
::Rcpp::internal::converter( x1 ),
::Rcpp::internal::converter( x2 )) ) ;
} catch( std::exception& __ex__ ){
forward_exception_to_r( __ex__ ) ;
} catch(...){
::Rf_error( "c++ exception (unknown reason)" ) ;
}
return res ;
}
int foobar__rcpp__wrapper__(int x, int y, NumericVector z){
return x + y + z.size() ;
}
The idea is that .Call expects a function that takes 0 or more SEXP and
returns one SEXP, so the macro creates one : "foobar"
foobar then calls another function "foobar__rcpp__wrapper__" and takes
care of:
- wraps the input SEXP in an Rcpp::internal::converter object. The
converter class has a templated conversion operator that delegates to
Rcpp::as :
template <typename T> operator T(){
return ::Rcpp::as<T>( x ) ;
}
- wraps the result back into a SEXP using Rcpp::wrap
- encloses the whole thing in an explicit try/catch/forward
The use of macros might be disrupting but the benefit is that this goes
one step further in letter the developper express the code in terms of
C++ rather than in terms of R data structures.
I'm using this e.g. in the highlight package with a function that looks
like this:
RCPP_FUNCTION_8(CharacterVector,get_highlighted_text,
List data, int start, int end, std::string space,
std::string newline, std::string prompt,
std::string continuePrompt, bool initial_spaces ){
...
}
What sort of bothers me is the _3, _8 suffix. Does anyone have
preprocessor tricks so that we could have for example a RCPP_FUNCTION
macro counting the number of arguments and then doing the right thing.
There is also the RCPP_FUNCTION_NODECL_* macro that are identical except
the first line is not included so that it can be included in a header file.
Romain
--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/9aKDM9 : embed images in Rd documents
|- http://tr.im/OIXN : raster images and RImageJ
|- http://tr.im/OcQe : Rcpp 0.7.7
More information about the Rcpp-devel
mailing list