Skip to content

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

8 messages · schattenpflanze at arcor.de, Dirk Eddelbuettel, Romain Francois

#
Hello,

I have made progress exposing my C++ classes to R with Rcpp-Modules and 
I really like the way it works. Thanks for this great package!

There are, however, lots of aspects about Rcpp which I do not yet fully 
understand. Here is one of them:
I have exposed a C++ class MyClass to R via an Rcpp module. Now I would 
like to write a C++ function, which creates (pointers to) objects of 
this class. The return type should ideally be a vector/list of pointers 
to the created C++ objects. The pointers should have the same type as 
those returned by the exposed constructors of MyClass in the module. In 
particular, I want R to do the memory management and garbage collection 
when I destroy the returned list of pointers.

When I try to directly wrap an object of type MyClass or a pointer to it 
or a List containing it, I get compiler errors. So I suppose this is not 
the way to do it. I can create a vector of Rcpp::XPtrs and return it 
successfully to R, but then I cannot use the objects in R in the same 
way as those created by the constructor, namely object_pointer$method().

Is there a way to achieve this or can you recommend a reasonable 
alternative design?
How are XPtrs related to the objects a Rcpp-Module class constructor 
returns, if at all?


Meta question:
Is there a search function for the Rcpp mailing list archive?


Thanks for your help,
Peter
#
Peter,
On 17 April 2011 at 10:45, schattenpflanze at arcor.de wrote:
| Hello,
| 
| I have made progress exposing my C++ classes to R with Rcpp-Modules and 
| I really like the way it works. Thanks for this great package!
| 
| There are, however, lots of aspects about Rcpp which I do not yet fully 
| understand. Here is one of them:
| I have exposed a C++ class MyClass to R via an Rcpp module. Now I would 
| like to write a C++ function, which creates (pointers to) objects of 
| this class. The return type should ideally be a vector/list of pointers 
| to the created C++ objects. The pointers should have the same type as 
| those returned by the exposed constructors of MyClass in the module. In 
| particular, I want R to do the memory management and garbage collection 
| when I destroy the returned list of pointers.
| 
| When I try to directly wrap an object of type MyClass or a pointer to it 
| or a List containing it, I get compiler errors. So I suppose this is not 
| the way to do it. I can create a vector of Rcpp::XPtrs and return it 
| successfully to R, but then I cannot use the objects in R in the same 
| way as those created by the constructor, namely object_pointer$method().
| 
| Is there a way to achieve this or can you recommend a reasonable 
| alternative design?
| How are XPtrs related to the objects a Rcpp-Module class constructor 
| returns, if at all?

Could you mock up a small example?
 
| Meta question:
| Is there a search function for the Rcpp mailing list archive?

I just constrain Google to, say, site:gmane.org to restrict the search to a
particular site.  And I also use grep on my folder with the list messages.

Dirk
#
Dirk,
Here is a small, abstract example which demonstrates one of the 
scenarios where I would like to create and return object pointers. There 
are two classes, A and B. Instances of A contain pointers to instances 
of B. I would like to create the B objects pointed to by A on demand, 
and query A for these. (In the actual application, both A and B are 
rather complex mathematical objects, which require a lot of work to 
compute. They are not only created and stored, but also modified, 
swapped, removed, etc.)

This is the basic idea:

// B just stores an integer i here
class B {
   public:
     B(int i) : i(i) {}

     int get_i() {
       return i;
     }

   private:
     int i;
}

// 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)
   ;
}

In R, I would then like to do, e.g., this:

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

I could rephrase the question as follows: How do I create objects of the 
exposed classes within C++ in a way which allows me to return them to R?
OK, thank you.


Best regards,
Peter





Am 17.04.2011 10:45, schrieb schattenpflanze at arcor.de:
#
Le 18/04/11 10:04, schattenpflanze at arcor.de a ?crit :
I see. There is no easy way to do this. But there should. This makes a 
nice item for someone's TODO list.

I don't have much spare time ATM, anyone with the required skills or a 
budget to fund such an extension to Rcpp modules ?


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.

Romain

  
    
#
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
2 days later
#
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 :

  
    
#
Thanks a lot for your help!
I am looking forward to that :-).

Peter
#
Le 21/04/11 11:01, schattenpflanze at arcor.de a ?crit :
Don't hold your breath. This will need time to design and implement it 
right.