[Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules
Romain Francois
romain at r-enthusiasts.com
Mon May 16 10:33:24 CEST 2011
There is a mechanism for dispatching to the appropriate constructor, but
this needs extra work from you on the C++ side. I'm currently not
entirely happy about it, and this might change in the future for
something nicer.
Some information about it was posted on this thread:
http://article.gmane.org/gmane.comp.lang.r.rcpp/929/match=constructors
You essentially have to supply an extra function that decides if the
constructor is appropriate for the arguments that are passed in:
So your example would become something like this:
library('inline')
library('Rcpp')
test_code <-'
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) : min(min_), max(max_) {}
Uniform(double max_, std::string dummy_) : min(0.0), max(max_){
Rprintf("%s\\n", dummy_.c_str());
}
Uniform(double max_ ) : min(0.0), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif( n, min, max );
}
double min, max;
};
double range( Uniform* w) {
return w->max - w->min;
}
bool fun1( SEXP* args, int nargs){
if( nargs != 2 ) return false ;
if( TYPEOF(args[1]) == STRSXP ) return false ;
return true ;
}
bool fun2( SEXP* args, int nargs){
if( nargs != 2 ) return false ;
if( TYPEOF(args[1]) != STRSXP ) return false ;
return true ;
}
RCPP_MODULE(unif_module) {
class_<Uniform>( "Uniform" )
.constructor<double,double>("", &fun1 )
.constructor<double,std::string>("", &fun2)
.constructor<double>()
.field( "min", &Uniform::min )
.field( "max", &Uniform::max )
.method( "draw", &Uniform::draw )
.method( "range", &range )
;
}
'
fx <- cxxfunction( signature(), "" , include = test_code, plugin = "Rcpp" )
unif_module <- Module( "unif_module", getDynLib(fx) )
Uniform <- unif_module$Uniform
u1 <- new( Uniform, 0, 10 )
u1$min
u1$max
u1$range()
u1$draw( 10L )
u2 <- new( Uniform, 10, "test" )
u2$min
u2$max
u2$range()
u2$draw( 10L )
u3 <- new( Uniform, 10 )
u3$min
u3$max
u3$range()
u3$draw( 10L )
Romain
Le 13/05/11 16:35, Jelmer Ypma a écrit :
> Dear Rcpp-list,
>
> I'm trying to expose multiple constructors of a C++ class to R using
> modules. Here is an example of what I want to do based on the Uniform
> example
>
> ===Begin: example
> library('inline')
> library('Rcpp')
>
> test_code<-'
> using namespace Rcpp;
>
> class Uniform {
> public:
> Uniform(double min_, double max_) : min(min_), max(max_) {}
> Uniform(double max_, std::string dummy_) : min(0.0), max(max_)
> { Rprintf("%s\\n", dummy_.c_str()); }
> Uniform(double max_ ) : min(0.0), max(max_) {}
>
> NumericVector draw(int n) const {
> RNGScope scope;
> return runif( n, min, max );
> }
>
> double min, max;
> };
>
> double range( Uniform* w) {
> return w->max - w->min;
> }
>
> RCPP_MODULE(unif_module) {
> class_<Uniform>( "Uniform" )
>
> .constructor<double,double>()
> .constructor<double,std::string>()
> .constructor<double>()
>
> .field( "min",&Uniform::min )
> .field( "max",&Uniform::max )
>
> .method( "draw",&Uniform::draw )
> .method( "range",&range )
> ;
> }
> '
>
> fx<- cxxfunction( signature(), "" , include = test_code, plugin = "Rcpp" )
> unif_module<- Module( "unif_module", getDynLib(fx) )
>
> show( Uniform )
> u1<- new( Uniform, 0, 10 )
> u1$min
> u1$max
> u1$range()
> u1$draw( 10L )
>
> u2<- new( Uniform, 10, "test" )
> u2$min
> u2$max
> u2$range()
> u2$draw( 10L )
>
> u3<- new( Uniform, 10 )
> u3$min
> u3$max
> u3$range()
> u3$draw( 10L )
> ===End: example
>
> Compilation works fine (on Windows using RTools, Rcpp_0.9.4.1,
> inline_0.3.8), but the R code cannot distinguish between two
> constructors with the same number of arguments, but with different
> types for the arguments and always calls Uniform(double, double). The
> output I get is as follows:
>
>> unif_module<- Module( "unif_module", getDynLib(fx) )
>
>> show( Uniform )
> C++ class 'Uniform'<02748CF0>
> Constructors:
> Uniform(double, double)
> Uniform(double, std::string)
> Uniform(double)
>
> Fields:
> double max
> double min
>
> Methods:
> Rcpp::NumericVector draw(int) const
>
> double range()
>
>
>> u1<- new( Uniform, 0, 10 )
>
>> u1$min
> [1] 0
>
>> u1$max
> [1] 10
>
>> u1$range()
> [1] 10
>
>> u1$draw( 10L )
> [1] 6.330045 4.637002 6.507183 4.192280 9.560602 3.927548 4.399107
> 2.332956 8.810553 3.864929
>
>> u2<- new( Uniform, 10, "test" )
> Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
> not compatible with REALSXP
>
>
> Does anyone know of a workaround for this?
>
> Many thanks in advance!
> Jelmer
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>
--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
http://romain-francois.com
|- http://bit.ly/hdKhCy : Rcpp article in JSS
|- http://bit.ly/elZJRJ : Montpellier Comedie Club - Avril 2011
`- http://bit.ly/fhqbRC : Rcpp workshop in Chicago on April 28th
More information about the Rcpp-devel
mailing list