That fixed it! Thanks, Chris
On Mon, Feb 6, 2012 at 11:09 AM, Romain Francois <rom...@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 >
_______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel