[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