[Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules

Jelmer Ypma jelmerypma at gmail.com
Mon May 16 14:03:47 CEST 2011


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
>
>
>


More information about the Rcpp-devel mailing list