That fixed it!<div><br></div><div>Thanks,</div><div>Chris<br><br><div class="gmail_quote">On Mon, Feb 6, 2012 at 11:09 AM, Romain Francois <span dir="ltr"><<a href="mailto:romain@r-enthusiasts.com">romain@r-enthusiasts.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Le 06/02/12 19:40, Chris DuBois a écrit :<div><div class="h5"><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi all,<br>
<br>
I have a class that stores data and various statistics about my data. I<br>
want to be able to work with it from R and from C++ functions, but I do<br>
not want to have the entire data structure created as an R object. I<br>
thought one might be able to return a pointer from the object to R, and<br>
pass that pointer from R to a C++ function that needs to interact with<br>
the object. This seems to work until garbage collection occurs, at<br>
which point I get a segfault.<br>
<br>
I have included an example below illustrating my current approach. I<br>
altered the World example to return a pointer to the current object. I<br>
have a C++ function that makes changes to the object.<br>
<br>
I saw this post<br>
<a href="http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-December/003214.html" target="_blank">http://lists.r-forge.r-<u></u>project.org/pipermail/rcpp-<u></u>devel/2011-December/003214.<u></u>html</a><br>
but I wanted to use modules and I haven't been able to adapt that<br>
solution to my situation.<br>
<br>
Any help/advice is much appreciated,<br>
Chris<br>
<br>
library(inline)<br>
library(Rcpp)<br>
fx <- cxxfunction(,"",includes=<br>
'<br>
#include <Rcpp.h><br>
<br>
class World {<br>
public:<br>
World() : msg("hello") {}<br>
void set(std::string msg) {<br>
this->msg = msg;<br>
}<br>
std::string greet() {<br>
return msg;<br>
}<br>
SEXP ptr() {<br>
return wrap(XPtr<World>(this, true));<br>
}<br>
<br>
private:<br>
std::string msg;<br>
};<br>
<br>
int fn(SEXP ptr_) {<br>
World *s = XPtr<World>(ptr_);<br>
s->set("c++ function has been here");<br>
return 1;<br>
}<br>
<br>
RCPP_MODULE(example){<br>
using namespace Rcpp ;<br>
function("fn", &fn);<br>
class_<World>( "World")<br>
.constructor()<br>
.method( "greet", &World::greet ,<br>
"get the message")<br>
.method( "set", &World::set ,<br>
"set the message")<br>
.method( "ptr", &World::ptr ,<br>
"get a pointer");<br>
}<br>
', plugin="Rcpp")<br>
<br>
example <- Module("example",getDynLib(fx)<u></u>)<br>
<br>
s <- new(example$World)<br>
<br>
# Interact with World object from R<br>
s$greet()<br>
s$set("hello from R")<br>
s$greet()<br>
<br>
# Grab pointer to this World object<br>
s$ptr()<br>
<br>
# Call a c++ function that uses World object<br>
example$fn(s$ptr())<br>
s$greet() # c++ function has altered s, as desired<br>
<br>
# Causes segfault<br>
gc()<br>
</blockquote>
<br>
<br></div></div>
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.<br>
<br>
You could prevent the finalizer by using :<br>
<br>
SEXP ptr() {<br>
return XPtr<World>(this, false);<br>
}<br>
<br>
Also, you don't need wrap because XPtr has a SEXP operator inherited from RObject.<span class="HOEnZb"><font color="#888888"><br>
<br>
Romain<br>
<br>
<br>
-- <br>
Romain Francois<br>
Professional R Enthusiast<br>
<a href="tel:%2B33%280%29%206%2028%2091%2030%2030" value="+33628913030" target="_blank">+33(0) 6 28 91 30 30</a><br>
R Graph Gallery: <a href="http://addictedtor.free.fr/graphiques" target="_blank">http://addictedtor.free.fr/<u></u>graphiques</a><br>
blog: <a href="http://romainfrancois.blog.free.fr" target="_blank">http://romainfrancois.blog.<u></u>free.fr</a><br>
|- <a href="http://bit.ly/xbKv0R" target="_blank">http://bit.ly/xbKv0R</a> : Crawling facebook with R<br>
|- <a href="http://bit.ly/v3WB8S" target="_blank">http://bit.ly/v3WB8S</a> : ... And now for solution 17, still using Rcpp<br>
`- <a href="http://bit.ly/uaQDGr" target="_blank">http://bit.ly/uaQDGr</a> : int64: 64 bit integer vectors for R<br>
</font></span></blockquote></div><br></div>