Message-ID: <BANLkTinqCBXoiahmxA8=Bj59k5GCVBEDJg@mail.gmail.com>
Date: 2011-05-16T12:03:47Z
From: Jelmer Ypma
Subject: [Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules
In-Reply-To: <4DD0E154.6090503@r-enthusiasts.com>
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
>
>
>