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

_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to