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
[Rcpp-devel] Creating pointers to objects and wrapping them
8 messages · schattenpflanze at arcor.de, Dirk Eddelbuettel, Romain Francois
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 Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
Dirk,
Could you mock up a small example?
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?
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.
OK, thank you. Best regards, Peter Am 17.04.2011 10:45, schrieb schattenpflanze at arcor.de:
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
_______________________________________________ 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
Le 18/04/11 10:04, schattenpflanze at arcor.de a ?crit :
Dirk,
Could you mock up a small example?
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?
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
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.
OK, thank you. Best regards, Peter Am 17.04.2011 10:45, schrieb schattenpflanze at arcor.de:
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
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
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
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 :
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
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.
Thanks a lot for your help!
Things will get much simpler when we figure out a way to return classes exposed by modules and implement it.
I am looking forward to that :-). Peter
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 21/04/11 11:01, schattenpflanze at arcor.de a ?crit :
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.
Thanks a lot for your help!
Things will get much simpler when we figure out a way to return classes exposed by modules and implement it.
I am looking forward to that :-).
Don't hold your breath. This will need time to design and implement it right.
Peter
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
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