[Rcpp-devel] Creating pointers to objects and wrapping them

Romain Francois romain at r-enthusiasts.com
Thu Apr 21 10:45:20 CEST 2011


Hello,

The approach here is to use a callback to the new function of R, to 
mimic the call :

b <- new( B, 0L )

which you can do for example using the Language class:

namespace Rcpp {
     template <>
     SEXP wrap( const B& object ){
         Language call( "new", Symbol( "B" ), object.get_i() ) ;
         return call.eval() ;
     }
}

Now, for Rcpp classes to be aware of a custom wrap, you need some 
gymnatics, as described in the Rcpp-extending vignette.
You need to include RcppCommon.h first, define you class and declare the 
custom wrap, then include Rcpp.h, then define you wrap.

I'm pasting a full pass at it below. Consider using the verbose = TRUE 
argument of cxxfunction to see what C++ code is being generated.

Things will get much simpler when we figure out a way to return classes 
exposed by modules and implement it.

Romain


require( inline )
require( Rcpp )

settings <- getPlugin("Rcpp")
settings$includes <- sprintf( "%s\n%s",
'
#include <RcppCommon.h>
// B just stores an integer i here
class B {
   public:
     B(int i) : i(i) {}

     int get_i() const {
       return i;
     }

   private:
     int i;
}  ;
namespace Rcpp{
     template <>
     SEXP wrap( const B& object ) ;
}
',
settings$includes
     )

inc <- '
namespace Rcpp {
     template <>
     SEXP wrap( const B& object ){
         Language call( "new", Symbol( "B" ), object.get_i() ) ;
         return call.eval() ;
     }
}

// A contains a vector v of pointers to B
class A {
   public:
     A(int n) : v(n) {}

     // THIS IS THE METHOD I WOULD LIKE TO IMPLEMENT:
     SEXP foo(int j) {
       if (!v[j]) {
         v[j] = new B(j);
       }

       // THIS DOES NOT WORK:
       return wrap(*v[j]);
     }

   private:
     std::vector<B*> v;
} ;

// Rcpp module exposing both A and B
RCPP_MODULE(MyModule) {
   class_<A>( "A" )
     .constructor<int>(
             "Create an instance of A with a given number of pointers")
     .method("foo",
             &A::foo,
             "(Create and) get one of the objects of type B.")
   ;

   class_<B>( "B" )
     .constructor<int>("Create an instance of B from an int.")
     .property("i",
               &B::get_i)
   ;
}
'

fx <- cxxfunction( , '

', includes = inc, settings = settings )
populate( Module( "MyModule", getDynLib( fx ) ), env = .GlobalEnv )

a <- new (A, 5)
b <- a$foo(0)
b$i







Le 18/04/11 16:12, schattenpflanze at arcor.de a écrit :
>> The way you try to implement it would require the class B to be
>> wrappable. You can have a look at the Rcpp-extending vignette for how to
>> enable wrap for custom classes.
> The vignette states that I should specialize the wrap template or
> implement the operator SEXP() for my class B. Unfortunately, it does not
> give any hint about how to create an appropriate SEXP from an arbitrary
> object pointer. After doing some research on the internet and a look at
> the Matrix package I came up with the following approach. Could
> something along these lines work at all?
>
> #include <Rdefines.h>
>
> SEXP foo() {
> B* b = new B(1);
> Rcpp::XPtr<B> xptr(b);
> SEXP s4_obj = PROTECT(NEW_OBJECT(MAKE_CLASS("Rcpp_B")));
> SEXP slot = Rcpp::wrap(std::string("pointer"));
> SET_SLOT(s4_obj, slot, xptr);
> UNPROTECT(1);
>
> return s4_obj;
> }
>
> Unfortunately, this does not work as expected. In R, the returned
> variable has type "S4", which is what I want. It cannot be used, though:
> Error in get(".pointer", envir = env) : Object '.pointer' not found.
> Perhaps all that is missing is a way to correctly initialize the
> "pointer" or ".xData" of the created object. Any hints on that?
>
> On the other hand, since I do not really understand in detail what
> happens here, the code above could also be perfect nonsense...
>
> Best regards,
> Peter

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