[Rcpp-devel] Passing XPtr between functions

Krzysztof Sakrejda krzysztof.sakrejda at gmail.com
Wed Jun 24 17:19:54 CEST 2015


Hi Charles, comments inline

2015-06-24 11:03 GMT-04:00 Charles Determan <cdetermanjr at gmail.com>:

> The fastLm examples are nice but they don't contain anything relating to
> passing an XPtr between functions.  Regarding your comment about making an
> XPtr around arma::mat 'innards' I'm not sure I fully understand.  I tried
> creating an XPtr around a arma::mat but no success on passing the object
> between functions.  It still returns that ~zeros.
>
> // [[Rcpp::export]]
> SEXP testXptr(SEXP A)
> {
>     arma::Mat<double> armaMat = as<arma::mat>(A);
>     XPtr<arma::mat> pMat(&armaMat);
>     return(pMat);
> }
>

When testXptr returns, armaMat is gone so it doesn't matter what you do
with pMat.  You need to use "new" to create armaMat and hand it over to
XPtr as above.  Then XPtr is returned to R. When XPtr is returned to R it's
protected from R's garbage collection by having a reference (reference?
something like that) to it in R.  armaMat lives on since it was created
with "new".  When you delete the XPtr in R, _it_ gets garbage-collected and
the destructor for XPtr calls "delete" on armaMat.  Then armaMat is gone
and you don't have a memory leak.  So the scheme is:

1) Create object of class Whatever in C++ using new.
2) Wrap object in XPtr<Whatever>
3) Return XPTr<Whatever> to R and save it to a variable.
4) Pass XPtr<Whatever> to any functions that need the object of class
Whatever
5) When you don't need the object of class Whatever, remove  XPtr<Whatever>
from the R session
6) R does gc on XPtr<Whatever>, which has a destructor.
7) Destructor from XPtr<Whatever> does "delete" on object of class Whatever.

Been a few months since I used this but I'm sure someone will correct me if
I'm not quite right here.  There really ought to be (and might already be)
an Rcpp gallery item about this process.  I'll sign up to make on later
this summer :)

Krzysztof



>
> // [[Rcpp::export]]
> void testReturn(SEXP ptrA, int nr, int nc)
> {
>     XPtr<arma::mat> ptrB(ptrA);
>     arma::mat B = arma::mat( (double *) ptrB->memptr(),
>           nr,
>           nc,
>           false);
>     B.print("copied matrix");
> }
>
> Charles
>
> On Wed, Jun 24, 2015 at 8:32 AM, Dirk Eddelbuettel <edd at debian.org> wrote:
>
>>
>> On 24 June 2015 at 08:22, Charles Determan wrote:
>> | Thank you John,
>> |
>> | I am familiar with bigmemory (I am one of the current developers
>> actually).
>> | The project I am working on doesn't need the shared memory aspect so was
>> | intending to avoid the dependency and just leverage the more familiar
>> and
>> | developed Armadillo library.  However your response informs me that I
>> did not
>> | fully understand how armadillo objects are handled.  I have some other
>> ideas
>> | with how I can address my problem but this was something I was hoping
>> to apply
>> | both for this project and for the sake of learning.
>>
>> Look at more current RcppArmadillo examples, and in particular _all_ the
>> variants of the fastLm benchmark in examples.  By doing the explicit cast,
>> you _forced_ a copy which may then have destroyed the Xptr link.  I
>> *think*
>> you could just do XPtr around arma::mat innards.  I would actually be
>> interested in having something somewhere between bigmemory (where I was
>> one
>> of the first external users) and what we have in RcppArmadillo.
>>
>> Dirk, during a break of Rcpp class in Zuerich
>>
>> | Regards,
>> | Charles
>> |
>> | On Tue, Jun 23, 2015 at 9:29 PM, John Buonagurio <
>> jbuonagurio at exponent.com>
>> | wrote:
>> |
>> |     Hi Charles,
>> |
>> |     > SEXP testXptr(SEXP A)
>> |     > {
>> |     >     arma::Mat<double> armaMat = Rcpp::as<arma::Mat<double> >(A);
>> |     >     Rcpp::XPtr<double> pMat(armaMat.memptr());
>> |     >     return(pMat);
>> |     > }
>> |
>> |     armaMat is on the stack, so the Armadillo memptr is no longer valid
>> when
>> |     you return from the testXptr function.
>> |
>> |     One simple solution in your case would be to dynamically allocate
>> with
>> |     "new" [e.g. arma::mat *A = new arma::mat(...);], though I can't
>> tell you
>> |     off hand how object lifetime is managed with Armadillo objects.
>> |
>> |     If you're trying to preserve a matrix across function calls in R,
>> have you
>> |     looked into bigmemory? http://gallery.rcpp.org/articles/
>> |     using-bigmemory-with-rcpp/
>> |
>> |     John
>> |
>> |
>> |
>> | _______________________________________________
>> | Rcpp-devel mailing list
>> | Rcpp-devel at lists.r-forge.r-project.org
>> | https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>
>> --
>> http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
>>
>
>
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20150624/c4c24c33/attachment-0001.html>


More information about the Rcpp-devel mailing list