[Rcpp-devel] Rcpp modules and parsing an object back and forth between R & C++

Romain Francois romain at r-enthusiasts.com
Wed Feb 20 09:17:55 CET 2013


Le 19/02/13 18:19, Hadley Wickham a écrit :
>> Unfortunately, at the moment modules and attributes don't play together. The
>> attributes feature used to be built on top of modules, but this caused
>> issues on windows.
>>
>> One thing we could perhaps negociate with JJ is recognition of the export
>> attribute on module. Something like :
>>
>> // [[Rcpp::export]]
>> RCPP_MODULE(SimpleModule) {
>>    class_<Simple>( "Simple")
>>          .constructor<double>()
>>          .const_method("times", &Simple::times)
>>    ;
>> }
>>
>> or perhaps even just recognizing the RCPP_MODULE declaration.
>
> That'd be cool!
>
>> Once we have that, you won't need the SEXP constructor or the SEXP
>> conversion operator, and you would only need that before your class
>> declaration:
>>
>> RCPP_EXPOSED_CLASS(Simple)
>>
>> So that as and wrap are taken care of.
>
> Until that happens, is it possible to write my own as and wrap methods?
>
> Hadley

Sure.

For as, You can get a Simple* using this:

Simple* obj = as_module_object<Simple>(x) ;

For the details, see as.h, this will call this:

         template <typename T> object<T> as_module_object(SEXP x){
             return (T*) as_module_object_internal(x) ;
         }

  and then this:

         namespace internal{
	    void* as_module_object_internal(SEXP obj){
	        Environment env(obj) ;
	        SEXP xp = env.get(".pointer") ;
	        return R_ExternalPtrAddr(xp );
	    }
	}
	
which uses the way we structured the c++ class around the reference class.

but writing RCPP_EXPOSED_AS(Simple) is enough I think so that you get 
"as<Simple>" directly.


For wrap, using RCPP_EXPOSED_WRAP(Simple) will just define a class trait 
that the dispatch maze uses:

#define RCPP_EXPOSED_WRAP(CLASS) namespace Rcpp{ namespace traits{ 
template<> struct wrap_type_traits< CLASS >{typedef 
wrap_type_module_object_tag wrap_category ; } ; }}

So that wrap<Simple>( const Simple& ) dispatches to:

template <typename T>
inline SEXP wrap_dispatch( const T& object, 
::Rcpp::traits::wrap_type_module_object_tag ){
	return Rcpp::internal::make_new_object<T>( new T(object) ) ;	
}

so you could call make_new_object directly I guess.

make_new_object is the function that actually uses the way we structured 
the c++ class representation around the ref class:

      namespace internal {
         template <typename Class>
         SEXP make_new_object( Class* ptr ){
             Rcpp::XPtr<Class> xp( ptr, true ) ;
             Function maker = Environment::Rcpp_namespace()[ 
"cpp_object_maker"] ;
             return maker( typeid(Class).name() , xp ) ;
         }
     }

This essentially calls the R function Rcpp:::cpp_object_maker

cpp_object_maker <- function(typeid, pointer){
     Class <- Rcpp:::.classes_map[[ typeid ]]
     new( Class, .object_pointer = pointer )
}

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://romainfrancois.blog.free.fr
|- http://bit.ly/14LJhmm : bibtex 0.3-5
`- http://bit.ly/RE6sYH  : OOP with Rcpp modules



More information about the Rcpp-devel mailing list