Yes, sorry for not being as quick with the follow-up, works exactly as described and perfect for my purposes.

I now wonder whether I could've done this with RCPP_EXPOSED_CLASS without creating and passing around the XPtr (at least, the module in this example http://romainfrancois.blog.free.fr/index.php?post/2012/10/25/Rcpp-modules-more-flexible accepts and returns a pointer to a class without explicit as/wrap-ing to XPtrs). But I'm quite happy with the solution Yan Zhou provided. Thanks again,

        Mike.

February 11, 2013 10:22 PM
On 11 February 2013 at 19:10, Yan Zhou wrote:
| It seems to me that XPtr is like an ownership pointer. It is much like
| unique_ptr. What you need here is a non-owning reference pointer, like
| weak_ptr.
|
| Have you tried
|
| XPtr<A> A::getPtr(){
| return(XPtr<A>(this, false));
| }
|
| With the optional argument, a finalizer is not set and the gc will not delete
| the C++ object. I haven't used XPtr in this way, but from the document I guess
| this shall work.

Nice work. Should have thought of the finalizer -- on quick testing this does
indeed do the trick. Well done.

Dirk

February 11, 2013 2:10 PM
It seems to me that XPtr is like an ownership pointer. It is much like unique_ptr. What you need here is a non-owning reference pointer, like weak_ptr.

Have you tried

XPtr<A> A::getPtr(){
   return(XPtr<A>(this, false));
}

With the optional argument, a finalizer is not set and the gc will not delete the C++ object. I haven't used XPtr in this way, but from the document I guess this shall work.

Best,

Yan Zhou



February 11, 2013 1:55 PM
Hi Dirk --

    Thanks for the quick response. My design is (I think) textbook aggregation -- in my case, A is a logger class and B is an experiment class. The experiment calls methods from the logger, but the logger may be active for more than one experiment so it can't be created inside it. So I create the logger and pass a pointer to it into the experiment. There are definitely other ways to design this, but this way doesn't seem to be particularly unreasonable.

    The basic goal is to create a C++ object on the R side (in this case, the logger class) and pass it back down to the C++ side for later use by another C++ object (the experiment class). I thought that XPtr was the right way to do this (based on e.g. http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-December/003214.html), but I could be misunderstanding either XPtrs or the example in that email. If there is a different way to pass down the Rcpp class and unwrap it to arrive at a pointer to the underlying C++ class, it would be great. Best,

        Mike.
February 11, 2013 12:40 PM
On 11 February 2013 at 12:16, Michael Shvartsman wrote:
| Hi Rcpp-devel -
|
| In some of my code, I return an XPtr pointing to one C++ class
| (e.g. class A) to the R side, and then pass it back down to the C++ side
| in the constructor of another class (e.g. class B, which needs access to
| some methods in class A). If I rm() both class A and the pointer to it
| on the R side (or they otherwise both go out of scope), then the garbage
| collector calls the destructor of class A twice and attempts to free the
| memory twice.
|
| Happens on OSX and Ubuntu with latest R and Rcpp. Is this intended
| behavior? If yes, what's a recommended workaround? I can go into more
| detail on why this is useful to my workflow if needed. Below is a
| minimal example. Best,

Thanks for sending a complete example -- very helpful.

I will think about this some more, but my first gut reaction is that your
design is wrong. You are essentially "just" using XPtr to get two references
to the same memory, and then for all intends and purposes doing

x = new Something;
delete x;
delete x;

which also doesn't work. I have worked quite happily with XPtr in the past,
and so have others. I have however not mixed them with Modules, I think, so
maybe that enters.

But I think the best answers to the "I hurts when I do this" remains "well
then just don't it".

And I may well have missed something here...

Dirk

|
| Mike Shvartsman.
|
| -----
| library(Rcpp)
| library(inline)
|
| inc <- '
| using namespace Rcpp;
| class A{
| public:
| A();
| ~A();
| XPtr<A> getPtr();
| };
|
| XPtr<A> A::getPtr(){
| return(XPtr<A>(this));
| }
|
| A::A(){
| Rcout << "CTOR" << std::endl;
| }
|
| A::~A(){
| Rcout << "DTOR" << std::endl;
| }
|
| RCPP_MODULE(mod){
| class_<A>("A")
| .constructor()
| .method("getPtr", &A::getPtr)
| ;
| }
| '
|
| func <- cxxfunction(signature(), include=inc, plugin='Rcpp')
|
| mod <- Module('mod', getDynLib(func))
|
|
| A <- mod$A
|
| a <- new(A)
| aPtr <- a$getPtr()
| rm(a)
| rm(aPtr)
| gc()
| -----
|
| _______________________________________________
| 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

February 11, 2013 12:16 PM
Hi Rcpp-devel -

    In some of my code, I return an XPtr pointing to one C++ class (e.g. class A) to the R side, and then pass it back down to the C++ side in the constructor of another class (e.g. class B, which needs access to some methods in class A). If I rm() both class A and the pointer to it on the R side (or they otherwise both go out of scope), then the garbage collector calls the destructor of class A twice and attempts to free the memory twice.

    Happens on OSX and Ubuntu with latest R and Rcpp. Is this intended behavior? If yes, what's a recommended workaround? I can go into more detail on why this is useful to my workflow if needed. Below is a minimal example. Best,

        Mike Shvartsman.

-----
library(Rcpp)
library(inline)

inc <- '
using namespace Rcpp;
class A{
    public:
        A();
        ~A();
        XPtr<A> getPtr();
};

XPtr<A> A::getPtr(){
    return(XPtr<A>(this));
}

A::A(){
    Rcout << "CTOR" << std::endl;
}

A::~A(){
    Rcout << "DTOR" << std::endl;
}

RCPP_MODULE(mod){
    class_<A>("A")
    .constructor()
    .method("getPtr", &A::getPtr)
    ;
}
'

func <- cxxfunction(signature(), include=inc, plugin='Rcpp')

mod <- Module('mod', getDynLib(func))


A <- mod$A

a <- new(A)
aPtr <- a$getPtr()
rm(a)
rm(aPtr)
gc()
-----

_______________________________________________
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

Reply via email to