[Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules
Thanks, this works for me. Jelmer
On Mon, May 16, 2011 at 10:33, Romain Francois <romain at r-enthusiasts.com> wrote:
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