[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