[Rcpp-devel] pointer to c++ object with modules

Chris DuBois chris.dubois at gmail.com
Mon Feb 6 20:25:45 CET 2012


That fixed it!

Thanks,
Chris

On Mon, Feb 6, 2012 at 11:09 AM, Romain Francois
<romain at r-enthusiasts.com>wrote:

> Le 06/02/12 19:40, Chris DuBois a écrit :
>
>  Hi all,
>>
>> I have a class that stores data and various statistics about my data.  I
>> want to be able to work with it from R and from C++ functions, but I do
>> not want to have the entire data structure created as an R object.  I
>> thought one might be able to return a pointer from the object to R, and
>> pass that pointer from R to a C++ function that needs to interact with
>> the object.  This seems to work until garbage collection occurs, at
>> which point I get a segfault.
>>
>> I have included an example below illustrating my current approach.  I
>> altered the World example to return a pointer to the current object.  I
>> have a C++ function that makes changes to the object.
>>
>> I saw this post
>> http://lists.r-forge.r-**project.org/pipermail/rcpp-**
>> devel/2011-December/003214.**html<http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-December/003214.html>
>>  but I wanted to use modules and I haven't been able to adapt that
>> solution to my situation.
>>
>> Any help/advice is much appreciated,
>> Chris
>>
>> library(inline)
>> library(Rcpp)
>> fx <- cxxfunction(,"",includes=
>> '
>> #include <Rcpp.h>
>>
>> class World {
>> public:
>>   World() : msg("hello") {}
>>   void set(std::string msg) {
>>     this->msg = msg;
>>   }
>>   std::string greet() {
>>     return msg;
>>   }
>>   SEXP ptr() {
>>     return wrap(XPtr<World>(this, true));
>>   }
>>
>> private:
>>   std::string msg;
>> };
>>
>> int fn(SEXP ptr_) {
>>   World *s = XPtr<World>(ptr_);
>>   s->set("c++ function has been here");
>>   return 1;
>> }
>>
>> RCPP_MODULE(example){
>> using namespace Rcpp ;
>> function("fn", &fn);
>> class_<World>( "World")
>>   .constructor()
>>   .method( "greet", &World::greet ,
>> "get the message")
>>   .method( "set", &World::set ,
>> "set the message")
>>   .method( "ptr", &World::ptr ,
>> "get a pointer");
>> }
>> ', plugin="Rcpp")
>>
>> example <- Module("example",getDynLib(fx)**)
>>
>> s <- new(example$World)
>>
>> # Interact with World object from R
>> s$greet()
>> s$set("hello from R")
>> s$greet()
>>
>> # Grab pointer to this World object
>> s$ptr()
>>
>> # Call a c++ function that uses World object
>> example$fn(s$ptr())
>> s$greet()  # c++ function has altered s, as desired
>>
>> # Causes segfault
>> gc()
>>
>
>
> That's subtle. When you call your ptr function, you create a new R
> external pointer to encapsulate the same underlying C++ pointer. When the R
> external pointer object you created goes out of scope, it becomes a
> candidat for gabage collection. When GC occurs, the undelying pointer is
> delete'd.
>
> You could prevent the finalizer by using :
>
> SEXP ptr() {
>    return XPtr<World>(this, false);
>  }
>
> Also, you don't need wrap because XPtr has a SEXP operator inherited from
> RObject.
>
> Romain
>
>
> --
> Romain Francois
> Professional R Enthusiast
> +33(0) 6 28 91 30 30
> R Graph Gallery: http://addictedtor.free.fr/**graphiques<http://addictedtor.free.fr/graphiques>
> blog:            http://romainfrancois.blog.**free.fr<http://romainfrancois.blog.free.fr>
> |- http://bit.ly/xbKv0R : Crawling facebook with R
> |- http://bit.ly/v3WB8S : ... And now for solution 17, still using Rcpp
> `- http://bit.ly/uaQDGr : int64: 64 bit integer vectors for R
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20120206/dd9b3634/attachment-0001.html>


More information about the Rcpp-devel mailing list